From 44df5ee7c84cb6591dfccbf1f3d26bb723690b4b Mon Sep 17 00:00:00 2001
From: Jan Cernik <66427541+jancernik@users.noreply.github.com>
Date: Fri, 3 Feb 2023 11:36:45 -0300
Subject: [PATCH] FIX: Allow keyboard navigation when searching emojis in chat
(#20157)
---
.../components/chat-emoji-picker.hbs | 53 ++++++-------
.../discourse/components/chat-emoji-picker.js | 11 ++-
.../stylesheets/common/chat-emoji-picker.scss | 8 +-
.../components/chat-emoji-picker-test.js | 76 +++++++++++++++++--
4 files changed, 115 insertions(+), 33 deletions(-)
diff --git a/plugins/chat/assets/javascripts/discourse/components/chat-emoji-picker.hbs b/plugins/chat/assets/javascripts/discourse/components/chat-emoji-picker.hbs
index e274c58f932..f4066e0e824 100644
--- a/plugins/chat/assets/javascripts/discourse/components/chat-emoji-picker.hbs
+++ b/plugins/chat/assets/javascripts/discourse/components/chat-emoji-picker.hbs
@@ -116,34 +116,36 @@
{{#if (gte this.filteredEmojis.length 0)}}
- {{#each this.filteredEmojis as |emoji|}}
-
- {{else}}
-
- {{i18n "chat.emoji_picker.no_results"}}
-
- {{/each}}
+
+ {{#each this.filteredEmojis as |emoji|}}
+
+ {{else}}
+
+ {{i18n "chat.emoji_picker.no_results"}}
+
+ {{/each}}
+
{{/if}}
{{#each-in this.groups as |section emojis|}}
@@ -158,7 +160,6 @@
(concat "chat.emoji_picker." section)
translatedFallback=section
}}
- {{on "keydown" this.didNavigateSection}}
>
{{i18n
diff --git a/plugins/chat/assets/javascripts/discourse/components/chat-emoji-picker.js b/plugins/chat/assets/javascripts/discourse/components/chat-emoji-picker.js
index 97ac5cd5b67..2c678e9d4bc 100644
--- a/plugins/chat/assets/javascripts/discourse/components/chat-emoji-picker.js
+++ b/plugins/chat/assets/javascripts/discourse/components/chat-emoji-picker.js
@@ -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
didNavigateSection(event) {
const sectionsEmojis = (section) => [...section.querySelectorAll(".emoji")];
@@ -247,7 +256,7 @@ export default class ChatEmojiPicker extends Component {
};
const allEmojis = () => [
...document.querySelectorAll(
- ".chat-emoji-picker__scrollable-content .emoji"
+ ".chat-emoji-picker__section:not(.hidden) .emoji"
),
];
diff --git a/plugins/chat/assets/stylesheets/common/chat-emoji-picker.scss b/plugins/chat/assets/stylesheets/common/chat-emoji-picker.scss
index bc61941f3a4..45866b708ed 100644
--- a/plugins/chat/assets/stylesheets/common/chat-emoji-picker.scss
+++ b/plugins/chat/assets/stylesheets/common/chat-emoji-picker.scss
@@ -98,7 +98,8 @@
}
}
- &__section-emojis {
+ &__section-emojis,
+ &__section.filtered {
padding: 0.5rem;
}
@@ -164,18 +165,23 @@
&.t1 {
background: #ffcc4d;
}
+
&.t2 {
background: #f7dece;
}
+
&.t3 {
background: #f3d2a2;
}
+
&.t4 {
background: #d5ab88;
}
+
&.t5 {
background: #af7e57;
}
+
&.t6 {
background: #7c533e;
}
diff --git a/plugins/chat/test/javascripts/components/chat-emoji-picker-test.js b/plugins/chat/test/javascripts/components/chat-emoji-picker-test.js
index 134fdf8f147..6856da9c522 100644
--- a/plugins/chat/test/javascripts/components/chat-emoji-picker-test.js
+++ b/plugins/chat/test/javascripts/components/chat-emoji-picker-test.js
@@ -3,7 +3,7 @@ import { exists, query, queryAll } from "discourse/tests/helpers/qunit-helpers";
import hbs from "htmlbars-inline-precompile";
import { module, test } from "qunit";
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() {
return {
@@ -138,26 +138,26 @@ module("Discourse Chat | Component | chat-emoji-picker", function (hooks) {
await fillIn(".dc-filter-input", "grinning");
assert.strictEqual(
- queryAll(".chat-emoji-picker__sections > img").length,
+ queryAll(".chat-emoji-picker__section.filtered > img").length,
1,
"it filters the emojis list"
);
assert.true(
- exists('.chat-emoji-picker__sections > img[alt="grinning"]'),
+ exists('.chat-emoji-picker__section.filtered > img[alt="grinning"]'),
"it filters the correct emoji"
);
await fillIn(".dc-filter-input", "Grinning");
assert.true(
- exists('.chat-emoji-picker__sections > img[alt="grinning"]'),
+ exists('.chat-emoji-picker__section.filtered > img[alt="grinning"]'),
"it is case insensitive"
);
await fillIn(".dc-filter-input", "smiley_cat");
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"
);
});
@@ -173,6 +173,72 @@ module("Discourse Chat | Component | chat-emoji-picker", function (hooks) {
assert.strictEqual(selection, "grinning");
});
+ test("When navigating sections", async function (assert) {
+ await render(hbs``);
+
+ 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``);
+ 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) {
let selection;
this.chatEmojiPickerManager.didSelectEmoji = (emoji) => {