From a91ad81ed1e81ef0fd63e4d2c90b3e41daedb5d9 Mon Sep 17 00:00:00 2001 From: Penar Musaraj Date: Wed, 9 Oct 2019 13:28:07 -0400 Subject: [PATCH] UX: Trigger primary action in modals using Enter A modal's primary action (blue button in the default theme) can now be invoked by hitting Enter on the keyboard. This applies to all modals that aren't strict forms as long as the focus is not on a textarea element. --- .../discourse/components/d-modal.js.es6 | 16 +++++++++ test/javascripts/acceptance/modal-test.js.es6 | 35 +++++++++++++++++++ 2 files changed, 51 insertions(+) diff --git a/app/assets/javascripts/discourse/components/d-modal.js.es6 b/app/assets/javascripts/discourse/components/d-modal.js.es6 index f870780789..f3ed9bcdbf 100644 --- a/app/assets/javascripts/discourse/components/d-modal.js.es6 +++ b/app/assets/javascripts/discourse/components/d-modal.js.es6 @@ -33,6 +33,10 @@ export default Ember.Component.extend({ if (e.which === 27 && this.dismissable) { Ember.run.next(() => $(".modal-header a.close").click()); } + + if (e.which === 13 && this.triggerClickOnEnter(e)) { + Ember.run.next(() => $(".modal-footer .btn-primary").click()); + } }); this.appEvents.on("modal:body-shown", this, "_modalBodyShown"); @@ -44,6 +48,18 @@ export default Ember.Component.extend({ this.appEvents.off("modal:body-shown", this, "_modalBodyShown"); }, + triggerClickOnEnter(e) { + // skip when in a form or a textarea element + if ( + $(e.target).parents("form").length > 0 || + (document.activeElement && document.activeElement.nodeName === "TEXTAREA") + ) { + return false; + } + + return true; + }, + mouseDown(e) { if (!this.dismissable) { return; diff --git a/test/javascripts/acceptance/modal-test.js.es6 b/test/javascripts/acceptance/modal-test.js.es6 index c15d23bd5c..45a7114672 100644 --- a/test/javascripts/acceptance/modal-test.js.es6 +++ b/test/javascripts/acceptance/modal-test.js.es6 @@ -52,3 +52,38 @@ QUnit.test("modal", async function(assert) { "ESC should not close the modal" ); }); + +acceptance("Modal Keyboard Events", { loggedIn: true }); + +QUnit.test("modal-keyboard-events", async function(assert) { + await visit("/t/internationalization-localization/280"); + + await click(".toggle-admin-menu"); + await click(".topic-admin-status-update button"); + await keyEvent(".d-modal", "keydown", 13); + + assert.ok( + find("#modal-alert:visible").length === 1, + "hitting Enter triggers modal action" + ); + assert.ok( + find(".d-modal:visible").length === 1, + "hitting Enter does not dismiss modal due to alert error" + ); + + await keyEvent("#main-outlet", "keydown", 27); + assert.ok( + find(".d-modal:visible").length === 0, + "ESC should close the modal" + ); + + await click(".topic-body button.reply"); + + await click(".d-editor-button-bar .btn.link"); + + await keyEvent(".d-modal", "keydown", 13); + assert.ok( + find(".d-modal:visible").length === 0, + "modal should disappear on hitting Enter" + ); +});