diff --git a/client/components/Menubar/MenubarItem.jsx b/client/components/Menubar/MenubarItem.jsx index 8d595bb5cd..c10459414c 100644 --- a/client/components/Menubar/MenubarItem.jsx +++ b/client/components/Menubar/MenubarItem.jsx @@ -19,6 +19,38 @@ function MenubarItem({ parent ]); + // Navigate menu-items using arrow_keys + handlers.onKeyDown = ({ key, target }) => { + const { parentNode: targetParentNode } = target; + + if (targetParentNode && targetParentNode.parentNode) { + const selector = + targetParentNode.parentNode.getAttribute('role') === 'menu' + ? '[role="menuitem"]' + : '[role="option"]'; + const nodes = targetParentNode.parentNode.querySelectorAll(selector); + + const targetIdx = Array.from(nodes).findIndex((node) => node === target); + if (targetIdx === -1) { + return; + } + + if (key === 'ArrowDown') { + const nextIdx = (targetIdx + 1) % nodes.length; + nodes[nextIdx]?.focus(); + } else if (key === 'ArrowUp') { + const prevIdx = targetIdx - 1 < 0 ? nodes.length - 1 : targetIdx - 1; + nodes[prevIdx]?.focus(); + } + } + }; + + // Ensures that the menu-items can be navigated using the arrow_keys + // from the place where the mouse is hovering + handlers.onMouseEnter = (event) => { + event.target.focus(); + }; + if (hideIf) { return null; } diff --git a/client/components/Menubar/MenubarSubmenu.jsx b/client/components/Menubar/MenubarSubmenu.jsx index 13b0e33177..6ec7202a50 100644 --- a/client/components/Menubar/MenubarSubmenu.jsx +++ b/client/components/Menubar/MenubarSubmenu.jsx @@ -28,6 +28,26 @@ export function useMenuProps(id) { function MenubarTrigger({ id, title, role, hasPopup, ...props }) { const { isOpen, handlers } = useMenuProps(id); + // Navigate to menu-items using arrow_keys + handlers.onKeyDown = ({ key, target }) => { + const ul = target.nextSibling; + if (ul) { + const selector = + ul.getAttribute('role') === 'menu' + ? '[role="menuitem"]' + : '[role="option"]'; + const nodes = ul.querySelectorAll(selector); + + if (key === 'ArrowDown') { + const nextIdx = 0; + nodes[nextIdx]?.focus(); + } else if (key === 'ArrowUp') { + const prevIdx = nodes.length - 1; + nodes[prevIdx]?.focus(); + } + } + }; + return (