Skip to content

Commit 58e5f43

Browse files
committed
fix: handle Enter/Space key on focused dropdown link items
When navigating to a link item in a dropdown menu using keyboard and pressing Enter or Space, the link was not being followed. Instead, the menu would close and reopen with the first item focused. The issue was that handleEnterOrSpace only checked if the dropdown button had browser focus, but menu items use aria-activedescendant pattern with tabindex="-1", so they never receive actual browser focus. Now the handler first checks for items with the data-focus attribute (our visual focus indicator) and simulates a click on them, which properly triggers link navigation for link items or click handlers for button items.
1 parent cb8b200 commit 58e5f43

File tree

2 files changed

+25
-1
lines changed

2 files changed

+25
-1
lines changed

assets/js/hooks/dropdown.js

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -151,7 +151,14 @@ export default {
151151
},
152152

153153
handleEnterOrSpace(e) {
154-
if (document.activeElement === this.refs.button) {
154+
const focusedItem = this.el.querySelector(SELECTORS.FOCUSED_MENUITEM)
155+
156+
if (focusedItem && focusedItem.getAttribute('aria-disabled') !== 'true') {
157+
// A menu item is focused - click it
158+
e.preventDefault()
159+
focusedItem.click()
160+
} else if (document.activeElement === this.refs.button) {
161+
// Button is focused - open menu
155162
e.preventDefault()
156163
this.showMenuAndFocusFirst()
157164
}

demo/test/wallaby/demo_web/dropdown_custom_components_test.exs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,4 +61,21 @@ defmodule DemoWeb.DropdownCustomComponentsTest do
6161
|> assert_has(Query.css("#dropdown-custom a[role=menuitem]:nth-child(2)[data-focus]"))
6262
|> assert_missing(Query.css("#dropdown-custom [role=menuitem]:nth-child(1)[data-focus]"))
6363
end
64+
65+
feature "pressing Enter on a focused link item navigates to the link", %{session: session} do
66+
session
67+
|> visit_fixture("/fixtures/dropdown-custom-components", "#dropdown-custom")
68+
|> click(@dropdown_trigger)
69+
|> assert_has(@dropdown_menu |> Query.visible(true))
70+
# Navigate down to the link item (which links to "/")
71+
|> send_keys([:down_arrow])
72+
|> send_keys([:down_arrow])
73+
|> assert_has(
74+
Query.css("#dropdown-custom a[role=menuitem]:nth-child(2)[data-focus]", text: "Link Item")
75+
)
76+
# Press Enter to follow the link
77+
|> send_keys([:enter])
78+
# Should navigate away from the fixture page - the dropdown should no longer exist
79+
|> assert_missing(@dropdown_container)
80+
end
6481
end

0 commit comments

Comments
 (0)