FIX: Allow keyboard navigation when searching emojis in chat (#20157)

This commit is contained in:
Jan Cernik
2023-02-03 11:36:45 -03:00
committed by GitHub
parent d5024d96f1
commit 44df5ee7c8
4 changed files with 115 additions and 33 deletions

View File

@ -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

View File

@ -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"
), ),
]; ];

View File

@ -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;
} }

View File

@ -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) => {