Context menu: keyboard navigation, checked items, anchoring, animation #317

Closed
opened 2026-10-07 20:43:22 -04:00 by Salastil · 1 comment
Owner

ContextMenu.tsx (89-130) is mouse-only: no role="menu"/menuitem, no arrow keys or initial focus, no checked/radio items (hence the " ✓" label hack in the status menu), no shortcut hints, no animation; it closes on resize but not on scroll or window blur; it always opens at the mouse, so the rail gear's menu isn't anchored to the gear (ServerRail.tsx:917-950).

Fix: all of the above.

Part of the v1.0 UI pass.

`ContextMenu.tsx` (89-130) is mouse-only: no `role="menu"`/`menuitem`, no arrow keys or initial focus, no checked/radio items (hence the " ✓" label hack in the status menu), no shortcut hints, no animation; it closes on resize but not on scroll or window blur; it always opens at the mouse, so the rail gear's menu isn't anchored to the gear (ServerRail.tsx:917-950). **Fix:** all of the above. _Part of the v1.0 UI pass._
Salastil added this to the v1.0 milestone 2026-10-07 20:43:22 -04:00
Salastil added the feature label 2026-10-07 20:43:22 -04:00
Author
Owner

Finished: 4065963.

The status menu - before (left) the current status was marked by appending " ✓" to its label; after (right) a real check at the edge:

status menu

The rail cog's menu - before (left), opened by a synthetic click it landed wherever the pointer was; after (right) it opens beside the button it belongs to (openFrom):

cog menu

  • Keyboard: arrow keys, Home and End move through the entries, Enter does the focused one, Tab or Escape closes the menu and gives focus back to where it was. Disabled entries are skipped.
  • role="menu", menuitem / menuitemcheckbox with aria-checked.
  • Checked entries (checked: true) and shortcut hints (shortcut: "Ctrl+K"), both optional fields on a menu entry; the status menu uses checked.
  • Fades and scales in (--motion-fast; still under reduced motion); closes when the window loses focus or something scrolls, as it has nothing to point at.
  • useContextMenu().openFrom(element) for menus that belong to a button.

Checked in the test copy with real key events: the menu takes focus, Down/Down/Up/End/Home move between Accounts / Downloads / Settings, and Enter on Accounts opened the panel and closed the menu; the status menu reports exactly one checked item. Not done: submenus, and type-to-jump.

Finished: [4065963](https://git.salastil.com/Salastil/moho/commit/40659636408c4530bb4731fed24327ef419436ef). **The status menu** - before (left) the current status was marked by appending " ✓" to its label; after (right) a real check at the edge: ![status menu](https://git.salastil.com/attachments/2d050016-ce6b-4385-9814-2af9f3b21c59) **The rail cog's menu** - before (left), opened by a synthetic click it landed wherever the pointer was; after (right) it opens beside the button it belongs to (`openFrom`): ![cog menu](https://git.salastil.com/attachments/3250d64f-3f10-4e8b-8a25-2f81d809ccd1) - **Keyboard**: arrow keys, Home and End move through the entries, Enter does the focused one, Tab or Escape closes the menu and gives focus back to where it was. Disabled entries are skipped. - `role="menu"`, `menuitem` / `menuitemcheckbox` with `aria-checked`. - **Checked entries** (`checked: true`) and **shortcut hints** (`shortcut: "Ctrl+K"`), both optional fields on a menu entry; the status menu uses `checked`. - **Fades and scales in** (`--motion-fast`; still under reduced motion); **closes when the window loses focus or something scrolls**, as it has nothing to point at. - `useContextMenu().openFrom(element)` for menus that belong to a button. Checked in the test copy with real key events: the menu takes focus, Down/Down/Up/End/Home move between Accounts / Downloads / Settings, and Enter on Accounts opened the panel and closed the menu; the status menu reports exactly one checked item. Not done: submenus, and type-to-jump.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: Salastil/moho#317