From 19006d6c17f9d8fdd924a18404679516d48be17a Mon Sep 17 00:00:00 2001 From: David Cook Date: Mon, 23 Mar 2026 16:20:40 +1100 Subject: [PATCH] Close action menu when making a selection But don't hide it immediately, because the user can't see if they made a selection, or accidentally closed it. Instead, fade slowly so that you can see the selected option momentarily (like system menus). This gives enough feedback while we wait for the selected action to perform. I did attempt a blink on the item background colour, like my favourite OS does which is really helpful. But couldn't get the CSS to work. --- .../vertical_ellipsis_menu_component.scss | 9 +++++++++ .../vertical_ellipsis_menu_controller.js | 16 ++++++++++++---- .../vertical_ellipsis_menu_controller_test.js | 14 +++++++++++++- 3 files changed, 34 insertions(+), 5 deletions(-) diff --git a/app/components/vertical_ellipsis_menu_component/vertical_ellipsis_menu_component.scss b/app/components/vertical_ellipsis_menu_component/vertical_ellipsis_menu_component.scss index 75e5e6da50..965519f3b7 100644 --- a/app/components/vertical_ellipsis_menu_component/vertical_ellipsis_menu_component.scss +++ b/app/components/vertical_ellipsis_menu_component/vertical_ellipsis_menu_component.scss @@ -29,6 +29,15 @@ display: block; } + // Fade out so user can see which option was selected + &.selected { + transition: + opacity 0.2s linear, + visibility 0.2s linear; + opacity: 0; + visibility: hidden; + } + & > a { display: block; padding: 5px 10px; diff --git a/app/components/vertical_ellipsis_menu_component/vertical_ellipsis_menu_controller.js b/app/components/vertical_ellipsis_menu_component/vertical_ellipsis_menu_controller.js index 97b13592bd..dbbe442c84 100644 --- a/app/components/vertical_ellipsis_menu_component/vertical_ellipsis_menu_controller.js +++ b/app/components/vertical_ellipsis_menu_component/vertical_ellipsis_menu_controller.js @@ -6,6 +6,9 @@ export default class extends Controller { connect() { super.connect(); window.addEventListener("click", this.#hideIfClickedOutside); + + // Close menu when making a selection + this.contentTarget.addEventListener("click", this.#selected.bind(this)); } disconnect() { @@ -13,17 +16,22 @@ export default class extends Controller { } toggle() { - this.contentTarget.classList.toggle("show"); + this.#toggleShow(); + } + + #selected() { + this.contentTarget.classList.add("selected"); } #hideIfClickedOutside = (event) => { if (this.element.contains(event.target)) { return; } - this.#hide(); + this.#toggleShow(false); }; - #hide() { - this.contentTarget.classList.remove("show"); + #toggleShow(force = undefined) { + this.contentTarget.classList.toggle("show", force); + this.contentTarget.classList.remove("selected"); } } diff --git a/spec/javascripts/stimulus/vertical_ellipsis_menu_controller_test.js b/spec/javascripts/stimulus/vertical_ellipsis_menu_controller_test.js index 1e8c7d1fbb..5a5956c45b 100644 --- a/spec/javascripts/stimulus/vertical_ellipsis_menu_controller_test.js +++ b/spec/javascripts/stimulus/vertical_ellipsis_menu_controller_test.js @@ -16,12 +16,13 @@ describe("VerticalEllipsisMenuController test", () => {
...
- +
`; const button = document.getElementById("button"); const content = document.getElementById("content"); + const item = document.getElementById("item"); }); it("add show class to content when toggle is called", () => { @@ -43,4 +44,15 @@ describe("VerticalEllipsisMenuController test", () => { document.body.click(); expect(content.classList.contains("show")).toBe(false); }); + + it("adds selected class to content when clicking a menu item", () => { + button.click(); + expect(content.classList.contains("selected")).toBe(false); + item.click(); + expect(content.classList.contains("selected")).toBe(true); + + // and removes it again when clicking button again + button.click(); + expect(content.classList.contains("selected")).toBe(false); + }); });