From 142ae3b5e54e578be07694ea03a1d4f2aaec8f2f Mon Sep 17 00:00:00 2001 From: Joffrey JAFFEUX Date: Tue, 10 May 2022 13:41:02 +0200 Subject: [PATCH] UX: allows to close popover on escape (#16698) --- .../discourse/app/components/d-popover.js | 2 ++ .../discourse/app/lib/d-popover.js | 24 +++++++++++++++++++ .../integration/components/d-popover-test.js | 16 ++++++++++++- 3 files changed, 41 insertions(+), 1 deletion(-) diff --git a/app/assets/javascripts/discourse/app/components/d-popover.js b/app/assets/javascripts/discourse/app/components/d-popover.js index 6e2d25f456..1a3b0ea9b0 100644 --- a/app/assets/javascripts/discourse/app/components/d-popover.js +++ b/app/assets/javascripts/discourse/app/components/d-popover.js @@ -4,6 +4,7 @@ import tippy from "tippy.js"; import { guidFor } from "@ember/object/internals"; import { action } from "@ember/object"; import { next } from "@ember/runloop"; +import { hideOnEscapePlugin } from "discourse/lib/d-popover"; export default class DiscoursePopover extends Component { tagName = ""; @@ -50,6 +51,7 @@ export default class DiscoursePopover extends Component { allowHTML: false, appendTo: "parent", hideOnClick: true, + plugins: [hideOnEscapePlugin], content: this.options?.content || document diff --git a/app/assets/javascripts/discourse/app/lib/d-popover.js b/app/assets/javascripts/discourse/app/lib/d-popover.js index 103faf96bf..0162bf2a01 100644 --- a/app/assets/javascripts/discourse/app/lib/d-popover.js +++ b/app/assets/javascripts/discourse/app/lib/d-popover.js @@ -3,6 +3,29 @@ import { run } from "@ember/runloop"; import tippy from "tippy.js"; import { iconHTML } from "discourse-common/lib/icon-library"; +export const hideOnEscapePlugin = { + name: "hideOnEscape", + + defaultValue: true, + + fn({ hide }) { + function onKeyDown(event) { + if (event.keyCode === 27) { + hide(); + } + } + + return { + onShow() { + document.addEventListener("keydown", onKeyDown); + }, + onHide() { + document.removeEventListener("keydown", onKeyDown); + }, + }; + }, +}; + export function hidePopover(event) { if (event?.target?._tippy) { showPopover(event); @@ -20,6 +43,7 @@ export function showPopover(event, options = {}) { trigger: "mouseenter click", hideOnClick: true, zIndex: 1400, + plugins: [hideOnEscapePlugin], }, options ); diff --git a/app/assets/javascripts/discourse/tests/integration/components/d-popover-test.js b/app/assets/javascripts/discourse/tests/integration/components/d-popover-test.js index a0608adcac..462127e418 100644 --- a/app/assets/javascripts/discourse/tests/integration/components/d-popover-test.js +++ b/app/assets/javascripts/discourse/tests/integration/components/d-popover-test.js @@ -8,7 +8,7 @@ import { } from "discourse/tests/helpers/qunit-helpers"; import hbs from "htmlbars-inline-precompile"; import { showPopover } from "discourse/lib/d-popover"; -import { click } from "@ember/test-helpers"; +import { click, triggerKeyEvent } from "@ember/test-helpers"; discourseModule("Integration | Component | d-popover", function (hooks) { setupRenderingTest(hooks); @@ -85,4 +85,18 @@ discourseModule("Integration | Component | d-popover", function (hooks) { assert.ok(exists(".d-popover.foo")); }, }); + + componentTest("d-popover component closes on escape key", { + template: hbs`{{#d-popover as |state|}}{{d-button icon=(if state.isExpanded "chevron-up" "chevron-down")}}{{/d-popover}}`, + + async test(assert) { + await click(".btn"); + + assert.ok(exists(".d-popover.is-expanded")); + + await triggerKeyEvent(document, "keydown", 27); + + assert.notOk(exists(".d-popover.is-expanded")); + }, + }); });