mirror of
https://github.com/discourse/discourse.git
synced 2025-05-23 07:11:17 +08:00
FIX: Allow keyboard navigation when searching emojis in chat (#20157)
This commit is contained in:
@ -116,10 +116,11 @@
|
|||||||
<div
|
<div
|
||||||
class="chat-emoji-picker__sections"
|
class="chat-emoji-picker__sections"
|
||||||
{{on "click" this.didSelectEmoji}}
|
{{on "click" this.didSelectEmoji}}
|
||||||
{{on "keydown" this.didSelectEmoji}}
|
{{on "keydown" this.onSectionsKeyDown}}
|
||||||
role="button"
|
role="button"
|
||||||
>
|
>
|
||||||
{{#if (gte this.filteredEmojis.length 0)}}
|
{{#if (gte this.filteredEmojis.length 0)}}
|
||||||
|
<div class="chat-emoji-picker__section filtered">
|
||||||
{{#each this.filteredEmojis as |emoji|}}
|
{{#each this.filteredEmojis as |emoji|}}
|
||||||
<img
|
<img
|
||||||
width="32"
|
width="32"
|
||||||
@ -144,6 +145,7 @@
|
|||||||
{{i18n "chat.emoji_picker.no_results"}}
|
{{i18n "chat.emoji_picker.no_results"}}
|
||||||
</p>
|
</p>
|
||||||
{{/each}}
|
{{/each}}
|
||||||
|
</div>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
|
||||||
{{#each-in this.groups as |section emojis|}}
|
{{#each-in this.groups as |section emojis|}}
|
||||||
@ -158,7 +160,6 @@
|
|||||||
(concat "chat.emoji_picker." section)
|
(concat "chat.emoji_picker." section)
|
||||||
translatedFallback=section
|
translatedFallback=section
|
||||||
}}
|
}}
|
||||||
{{on "keydown" this.didNavigateSection}}
|
|
||||||
>
|
>
|
||||||
<h2 class="chat-emoji-picker__section-title">
|
<h2 class="chat-emoji-picker__section-title">
|
||||||
{{i18n
|
{{i18n
|
||||||
|
@ -231,6 +231,15 @@ export default class ChatEmojiPicker extends Component {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@action
|
||||||
|
onSectionsKeyDown(event) {
|
||||||
|
if (event.key === "Enter") {
|
||||||
|
this.didSelectEmoji(event);
|
||||||
|
} else {
|
||||||
|
this.didNavigateSection(event);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@action
|
@action
|
||||||
didNavigateSection(event) {
|
didNavigateSection(event) {
|
||||||
const sectionsEmojis = (section) => [...section.querySelectorAll(".emoji")];
|
const sectionsEmojis = (section) => [...section.querySelectorAll(".emoji")];
|
||||||
@ -247,7 +256,7 @@ export default class ChatEmojiPicker extends Component {
|
|||||||
};
|
};
|
||||||
const allEmojis = () => [
|
const allEmojis = () => [
|
||||||
...document.querySelectorAll(
|
...document.querySelectorAll(
|
||||||
".chat-emoji-picker__scrollable-content .emoji"
|
".chat-emoji-picker__section:not(.hidden) .emoji"
|
||||||
),
|
),
|
||||||
];
|
];
|
||||||
|
|
||||||
|
@ -98,7 +98,8 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&__section-emojis {
|
&__section-emojis,
|
||||||
|
&__section.filtered {
|
||||||
padding: 0.5rem;
|
padding: 0.5rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -164,18 +165,23 @@
|
|||||||
&.t1 {
|
&.t1 {
|
||||||
background: #ffcc4d;
|
background: #ffcc4d;
|
||||||
}
|
}
|
||||||
|
|
||||||
&.t2 {
|
&.t2 {
|
||||||
background: #f7dece;
|
background: #f7dece;
|
||||||
}
|
}
|
||||||
|
|
||||||
&.t3 {
|
&.t3 {
|
||||||
background: #f3d2a2;
|
background: #f3d2a2;
|
||||||
}
|
}
|
||||||
|
|
||||||
&.t4 {
|
&.t4 {
|
||||||
background: #d5ab88;
|
background: #d5ab88;
|
||||||
}
|
}
|
||||||
|
|
||||||
&.t5 {
|
&.t5 {
|
||||||
background: #af7e57;
|
background: #af7e57;
|
||||||
}
|
}
|
||||||
|
|
||||||
&.t6 {
|
&.t6 {
|
||||||
background: #7c533e;
|
background: #7c533e;
|
||||||
}
|
}
|
||||||
|
@ -3,7 +3,7 @@ import { exists, query, queryAll } from "discourse/tests/helpers/qunit-helpers";
|
|||||||
import hbs from "htmlbars-inline-precompile";
|
import hbs from "htmlbars-inline-precompile";
|
||||||
import { module, test } from "qunit";
|
import { module, test } from "qunit";
|
||||||
import pretender from "discourse/tests/helpers/create-pretender";
|
import pretender from "discourse/tests/helpers/create-pretender";
|
||||||
import { click, fillIn, render } from "@ember/test-helpers";
|
import { click, fillIn, render, triggerKeyEvent } from "@ember/test-helpers";
|
||||||
|
|
||||||
function emojisResponse() {
|
function emojisResponse() {
|
||||||
return {
|
return {
|
||||||
@ -138,26 +138,26 @@ module("Discourse Chat | Component | chat-emoji-picker", function (hooks) {
|
|||||||
await fillIn(".dc-filter-input", "grinning");
|
await fillIn(".dc-filter-input", "grinning");
|
||||||
|
|
||||||
assert.strictEqual(
|
assert.strictEqual(
|
||||||
queryAll(".chat-emoji-picker__sections > img").length,
|
queryAll(".chat-emoji-picker__section.filtered > img").length,
|
||||||
1,
|
1,
|
||||||
"it filters the emojis list"
|
"it filters the emojis list"
|
||||||
);
|
);
|
||||||
assert.true(
|
assert.true(
|
||||||
exists('.chat-emoji-picker__sections > img[alt="grinning"]'),
|
exists('.chat-emoji-picker__section.filtered > img[alt="grinning"]'),
|
||||||
"it filters the correct emoji"
|
"it filters the correct emoji"
|
||||||
);
|
);
|
||||||
|
|
||||||
await fillIn(".dc-filter-input", "Grinning");
|
await fillIn(".dc-filter-input", "Grinning");
|
||||||
|
|
||||||
assert.true(
|
assert.true(
|
||||||
exists('.chat-emoji-picker__sections > img[alt="grinning"]'),
|
exists('.chat-emoji-picker__section.filtered > img[alt="grinning"]'),
|
||||||
"it is case insensitive"
|
"it is case insensitive"
|
||||||
);
|
);
|
||||||
|
|
||||||
await fillIn(".dc-filter-input", "smiley_cat");
|
await fillIn(".dc-filter-input", "smiley_cat");
|
||||||
|
|
||||||
assert.true(
|
assert.true(
|
||||||
exists('.chat-emoji-picker__sections > img[alt="grinning"]'),
|
exists('.chat-emoji-picker__section.filtered > img[alt="grinning"]'),
|
||||||
"it filters the correct emoji using search alias"
|
"it filters the correct emoji using search alias"
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
@ -173,6 +173,72 @@ module("Discourse Chat | Component | chat-emoji-picker", function (hooks) {
|
|||||||
assert.strictEqual(selection, "grinning");
|
assert.strictEqual(selection, "grinning");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("When navigating sections", async function (assert) {
|
||||||
|
await render(hbs`<ChatEmojiPicker />`);
|
||||||
|
|
||||||
|
await triggerKeyEvent(document.activeElement, "keydown", "ArrowDown");
|
||||||
|
assert.strictEqual(
|
||||||
|
document.activeElement.dataset.emoji,
|
||||||
|
"grinning",
|
||||||
|
"ArrowDown focuses on the first favorite emoji"
|
||||||
|
);
|
||||||
|
|
||||||
|
await triggerKeyEvent(document.activeElement, "keydown", "ArrowDown");
|
||||||
|
await triggerKeyEvent(document.activeElement, "keydown", "ArrowDown");
|
||||||
|
assert.strictEqual(
|
||||||
|
document.activeElement.dataset.emoji,
|
||||||
|
"raised_hands",
|
||||||
|
"ArrowDown focuses on the first emoji form the third section"
|
||||||
|
);
|
||||||
|
|
||||||
|
await triggerKeyEvent(document.activeElement, "keydown", "ArrowRight");
|
||||||
|
assert.strictEqual(
|
||||||
|
document.activeElement.dataset.emoji,
|
||||||
|
"man_rowing_boat",
|
||||||
|
"ArrowRight focuses on the emoji at the right"
|
||||||
|
);
|
||||||
|
|
||||||
|
await triggerKeyEvent(document.activeElement, "keydown", "ArrowLeft");
|
||||||
|
assert.strictEqual(
|
||||||
|
document.activeElement.dataset.emoji,
|
||||||
|
"raised_hands",
|
||||||
|
"ArrowLeft focuses on the emoji at the left"
|
||||||
|
);
|
||||||
|
|
||||||
|
await triggerKeyEvent(document.activeElement, "keydown", "ArrowUp");
|
||||||
|
assert.strictEqual(
|
||||||
|
document.activeElement.dataset.emoji,
|
||||||
|
"grinning",
|
||||||
|
"ArrowUp focuses on the first emoji form the second section"
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("When navigating filtered emojis", async function (assert) {
|
||||||
|
await render(hbs`<ChatEmojiPicker />`);
|
||||||
|
await fillIn(".dc-filter-input", "man");
|
||||||
|
|
||||||
|
await triggerKeyEvent(document.activeElement, "keydown", "ArrowDown");
|
||||||
|
assert.strictEqual(
|
||||||
|
document.activeElement.dataset.emoji,
|
||||||
|
"man_rowing_boat",
|
||||||
|
"ArrowDown focuses on the first filtered emoji"
|
||||||
|
);
|
||||||
|
|
||||||
|
await triggerKeyEvent(document.activeElement, "keydown", "ArrowRight");
|
||||||
|
assert.strictEqual(
|
||||||
|
document.activeElement.dataset.emoji,
|
||||||
|
"womans_clothes",
|
||||||
|
"ArrowRight focuses on the emoji at the right"
|
||||||
|
);
|
||||||
|
|
||||||
|
await triggerKeyEvent(document.activeElement, "keydown", "ArrowLeft");
|
||||||
|
assert.strictEqual(
|
||||||
|
document.activeElement.dataset.emoji,
|
||||||
|
"man_rowing_boat",
|
||||||
|
"ArrowLeft focuses on the emoji at the left"
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
test("When selecting a toned an emoji", async function (assert) {
|
test("When selecting a toned an emoji", async function (assert) {
|
||||||
let selection;
|
let selection;
|
||||||
this.chatEmojiPickerManager.didSelectEmoji = (emoji) => {
|
this.chatEmojiPickerManager.didSelectEmoji = (emoji) => {
|
||||||
|
Reference in New Issue
Block a user