LearnNewsExamplesServices
Frontmatter
id18760
titlemenu.List: Right and Left no longer walk the submenu cascade
stateClosed
labels
bugairegressionaccessibility
assigneesneo-opus-ada
createdAtSep 16, 2026, 10:08 AM
updatedAtSep 16, 2026, 12:13 PM
githubUrlhttps://github.com/neomjs/neo/issues/18760
authorneo-opus-ada
commentsCount0
parentIssuenull
subIssues[]
subIssuesCompleted0
subIssuesTotal0
contentTrust
projected
quarantined0
signals[]
blockedBy[x] 18758 menu.List looks submenus up under a key they are not cached by
blocking[]
closedAtSep 16, 2026, 12:13 PM

menu.List: Right and Left no longer walk the submenu cascade

Closed v13.2.0/archive-v13-2-0-chunk-21 bugairegressionaccessibility
neo-opus-ada
neo-opus-ada commented on Sep 16, 2026, 10:08 AM

Context

Operator (2026-09-16): keyboard navigation through nested menus in examples/button/base once worked — arrows plus Space/Enter walked the cascade — and regressed when main.addon.Navigator arrived (#5123). The operator also ruled the pre-Navigator model out as the target: it selected on navigate and had no focus state. Focus as the cursor, with Space/Enter as the explicit select, is the intended UX.

Observed on dev@d688710175, examples/button/base, in-app browser with CDP key events. Each step starts from the previous one:

Step Result
Click Hello World Menu shows, focus on Item 1
ArrowDown ×2 Focus on Item 3 (a parent), nothing shown — correct under the focus model
ArrowRight on Item 3 nothing
Enter on Item 3 Submenu shows, focus moves to Item 4
ArrowDown Focus on Item 5
ArrowLeft on Item 5 nothing: submenu stays, focus stays inside it

The Problem

#5123 (2023-12-22) moved arrow navigation out of selection.ListModel#onNavKey, which selected the next item, into the Navigator, which moves focus. It left onKeyDown{Up,Down,Enter,Left,Right} as placeholders. selection.menu.ListModel still assumes selection is the cursor:

  • onKeyDownRight() calls view.activeSubMenu?.selectionModel.selectAt(0). A focused parent has no active submenu, so Right is a no-op. When one is showing, Right moves that submenu's selection, not focus.
  • onKeyDownLeft() re-selects parentMenu's item at parentIndex. It is already selected, so nothing changes: the submenu is never hidden and focus never moves.
  • Space: the Navigator activates on Enter only (case 'Enter' in its keydown handler), and no menu binds Space. This is a code reading, not yet run: the in-app browser's key instrument sends no key value for Space.

Enter works through a side effect: the Navigator clicks the item, selection shows the submenu, and component.Base#afterSetMounted focuses a floating component's first focusable child on mount.

The Fix — src/selection/menu/ListModel.mjs, src/menu/List.mjs

Inside the focus model (arrows move focus; Enter, Space and click select and activate):

  • Right on a focused parent shows its submenu and focuses the submenu's first item, including when the submenu is already showing. On a leaf: nothing.
  • Left in a submenu hides it and focuses its parent item. In the root: nothing.
  • Escape in a submenu hides that level and focuses its parent item. In the root: today's dismissal.
  • Space on a focused item does what Enter does. The binding is menu-local; the Navigator stays unchanged for every other list.
  • Up/Down stay focus-only: arrowing onto a parent shows nothing.

The focused item comes from the view's focus state (list.Base#focusIndex, which onListNavigate() already keeps current), never from selection.

Acceptance Criteria

  • AC-1 Right on a focused parent shows its submenu and focuses its first item; Right on a leaf changes nothing (component spec, real keyboard).
  • AC-2 Left in a submenu hides it and focuses the parent item; Left in the root changes nothing.
  • AC-3 Escape in a submenu hides only that level and focuses the parent item.
  • AC-4 Space on a parent behaves like Enter (shows its submenu, focus moves in); Space on a leaf runs its handler and dismisses like Enter.
  • AC-5 Up/Down onto a parent show nothing.
  • AC-6 A depth-2 walk by keyboard alone — Item 3 → Item 6 → Item 7, then back up to Item 3 — with focus on the expected item at every step.
  • AC-7 Existing menu unit and component specs stay green.

Out of Scope

  • Reintroducing selection on navigate (operator ruling above).
  • Pointer hover — #18759.
  • Changing the Navigator's key handling for other lists.

Follow-up — focus-rest preview (operator direction, 2026-09-16)

Keyboard focus resting on a parent would show its submenu the way a pointer rest does (#18759), and Up/Down off it would hide it again; Right then only moves focus into what is already showing. It needs #18759's non-focusing preview show — without it, the mount-focus above pulls the cursor into every previewed submenu — and it changes this ticket's Left to "focus the parent, keep its submenu showing". File when this ticket and #18759 have both merged.

Related

Blocked by #18758 · #5123 · #4606 · #4605

Live latest-open sweep: latest 20 open issues at 2026-09-16T08:07:16Z; no equivalent found A2A claim sweep: latest 30 inbox messages, all read-states, at 2026-09-16T08:07Z; no [lane-claim] / [lane-intent] on menus MC sweep: query_raw_memories on the symptom ("keyboard navigation nested menu submenu arrow right left does nothing; menu keynav regression after Navigator addon"), 6 results; a #14619-era note records Space as an uncovered edge of Enter-primary activation — consistent, no decision against. Git history: 00a67f1020 (#5123) removed onNavKey Own-assignment sweep: 5 open, none on src/menu or src/selection

Origin Session ID: fda7faab-19c5-43a0-b192-003966068172 Retrieval Hint: "menu.List keynav Right Left Escape Space focus model Navigator #5123 selection.menu.ListModel onKeyDownRight"

tobiu referenced in commit d66afd6 - "fix(menu): Right and Left walk the submenu cascade again, inside the focus model (#18760) on Sep 16, 2026, 11:00 AM
tobiu referenced in commit 99ebfde - "fix(menu): Right and Left walk the submenu cascade again, inside the focus model (#18760) on Sep 16, 2026, 11:29 AM
tobiu referenced in commit 17f5a83 - "fix(menu): Right and Left walk the submenu cascade again, inside the focus model (#18760) (#18766) on Sep 16, 2026, 12:13 PM
tobiu closed this issue on Sep 16, 2026, 12:13 PM
tobiu referenced in commit 08f9d60 - "feat(menu): focus rests like a pointer rests (#18780) (#18783) on Sep 16, 2026, 1:58 PM