enhancement
major
minor
defect
critical
major
minor
major
#30147
React Interface: The "More Actions" menu does not close when the Escape key is pressed if all items are disabled
Bug Description
A drop-down menu in the React interface (e.g., the "More Actions" overflow menu on a toolbar) does not close when the Escape key is pressed if all of its entries are disabled. It closes only when you click the menu button again or click outside the menu. As long as it is open, it obscures the elements beneath it (e.g., table rows), and clicks there trigger the menu.
If, on the other hand, the menu closes with the Escape key, the focus does not return to the menu button but instead lands on another button on the toolbar.
Test
tl-demo-react with the BPE modules, Administration -> Workflows: select a workflow, “More Actions” -> Delete -> Yes. Afterward, nothing is selected and all menu entries are disabled. Open “More Actions” and press Escape: the menu remains open.
Cause
`useRovingMenu ` in `com.top_logic.layout.react/react-src/bridge/menu.tsx ` handles the keys in the `onKeyDown ` event of the menu element. The focus remains on the menu even when no item is selected (the focus trap then focuses on the menu element itself), but the handler terminates as soon as there is no selected item—even before it checks for the Escape key.
When the menu closes, the focus trap returns the focus to the element that had it when the menu opened. Since the menu button deliberately does not take focus when opened with the mouse (the focus is supposed to remain on the content whose selection triggers the commands), this is any element that had focus previously.
Solution
- Pressing Escape closes the menu regardless of whether there are any selected items. This applies to all menus in the React interface (overflow menus and toolbar menu groups, context menus, sidebar flyouts, menus from `Menu ` / `TLMenu`) as well as to the menu in the MUI theme (`MuiMenuAdapter`).
- If the Escape key closes the menu, focus returns to the button that opened it (WAI-ARIA Menu Button). If an item is selected or a click occurs outside the menu, focus still returns to where it was before the menu opened. A menu without a trigger element (context menu at the mouse position) retains this behavior even when Escape is pressed.
Technical:
- New Bridge hook `useEscapeClose(open, onClose, trigger)`: closes the menu when Escape is pressed, remembers this, and returns `restoreTo`, which specifies the trigger element after an Escape-based closure. `useRovingMenu ` builds on this and accepts the trigger as an optional parameter.
- useFocusTrap has the restoreTo option, which determines the element that receives focus upon closing (otherwise, it is the element that had focus when the menu opened).
- Menu takes its anchor as the trigger if it is an element; the toolbar’s menu group takes its menu button.
- By the way: the typo in MuiTabBarAdapter.test.tsx (missing required ` hidden` field for the tab) has been fixed; `tsc ` now runs without errors for `com.top_logic.layout.react.mui `.