From 73fc40bb83ac2b14936e38ad2706cfdd68abc34f Mon Sep 17 00:00:00 2001 From: Cameron Dutro Date: Mon, 7 Aug 2023 09:47:10 -0700 Subject: [PATCH] ActionMenu: Don't allow items to be unchecked in single-select mode (#2192) --- .changeset/hot-rats-lie.md | 7 ++ .../alpha/action_menu/action_menu_element.ts | 11 ++- test/system/alpha/action_menu_test.rb | 68 +++++++++++++++++++ 3 files changed, 85 insertions(+), 1 deletion(-) create mode 100644 .changeset/hot-rats-lie.md diff --git a/.changeset/hot-rats-lie.md b/.changeset/hot-rats-lie.md new file mode 100644 index 0000000000..9750d6d993 --- /dev/null +++ b/.changeset/hot-rats-lie.md @@ -0,0 +1,7 @@ +--- +'@primer/view-components': patch +--- + +ActionMenu: Don't allow items to be unchecked in single-select mode + + diff --git a/app/components/primer/alpha/action_menu/action_menu_element.ts b/app/components/primer/alpha/action_menu/action_menu_element.ts index a0f5dded16..a49e918228 100644 --- a/app/components/primer/alpha/action_menu/action_menu_element.ts +++ b/app/components/primer/alpha/action_menu/action_menu_element.ts @@ -139,14 +139,23 @@ export class ActionMenuElement extends HTMLElement { if (!item) return const ariaChecked = item.getAttribute('aria-checked') const checked = ariaChecked !== 'true' - item.setAttribute('aria-checked', `${checked}`) + if (this.selectVariant === 'single') { + // Only check, never uncheck here. Single-select mode does not allow unchecking a checked item. + if (checked) { + item.setAttribute('aria-checked', 'true') + } + for (const checkedItem of this.querySelectorAll('[aria-checked]')) { if (checkedItem !== item) { checkedItem.setAttribute('aria-checked', 'false') } } + this.#setDynamicLabel() + } else { + // multi-select mode allows unchecking a checked item + item.setAttribute('aria-checked', `${checked}`) } this.#updateInput() diff --git a/test/system/alpha/action_menu_test.rb b/test/system/alpha/action_menu_test.rb index 0d54deb2d9..218eeb5fa5 100644 --- a/test/system/alpha/action_menu_test.rb +++ b/test/system/alpha/action_menu_test.rb @@ -278,5 +278,73 @@ def test_opening_second_menu_closes_first_menu refute_selector "action-menu ul li", text: "Eat a dot" assert_selector "action-menu ul li", text: "Stomp a turtle" end + + def test_single_select_item_checked + visit_preview(:single_select) + + find("action-menu button[aria-controls]").click + find("action-menu ul li:nth-child(2)").click + + # clicking item closes menu, so checked item is hidden + assert_selector "[aria-checked=true]", text: "Recursive", visible: :hidden + end + + def test_single_select_item_unchecks_previously_checked_item + visit_preview(:single_select) + + find("action-menu button[aria-controls]").click + find("action-menu ul li:nth-child(3)").click + + # clicking item closes menu, so checked item is hidden + refute_selector "[aria-checked=true]", text: "Recursive", visible: :hidden + + find("action-menu button[aria-controls]").click + find("action-menu ul li:nth-child(2)").click + + # clicking item closes menu, so checked item is hidden + assert_selector "[aria-checked=true]", text: "Recursive", visible: :hidden + end + + def test_single_selected_item_cannot_be_unchecked + visit_preview(:single_select) + + find("action-menu button[aria-controls]").click + find("action-menu ul li:nth-child(2)").click + + find("action-menu button[aria-controls]").click + find("action-menu ul li:nth-child(2)").click + + # clicking item closes menu, so checked item is hidden + assert_selector "[aria-checked=true]", text: "Recursive", visible: :hidden + end + + def test_multi_select_items_checked + visit_preview(:multiple_select) + + find("action-menu button[aria-controls]").click + find("action-menu ul li:nth-child(2)").click + find("action-menu ul li:nth-child(3)").click + + # clicking item closes menu, so checked item is hidden + assert_selector "[aria-checked=true]", text: "jonrohan" + assert_selector "[aria-checked=true]", text: "broccolinisoup" + end + + def test_multi_select_items_can_be_unchecked + visit_preview(:multiple_select) + + find("action-menu button[aria-controls]").click + find("action-menu ul li:nth-child(2)").click + find("action-menu ul li:nth-child(3)").click + + # clicking item closes menu, so checked item is hidden + assert_selector "[aria-checked=true]", text: "jonrohan" + assert_selector "[aria-checked=true]", text: "broccolinisoup" + + find("action-menu ul li:nth-child(2)").click + find("action-menu ul li:nth-child(3)").click + + refute_selector "[aria-checked=true]" + end end end