Skip to content

fix(ui-ng): make flr-menu keyboard navigable - #679

Merged
BryanFRD merged 5 commits into
mainfrom
fix/675-menu-keyboard-nav
Oct 25, 2026
Merged

BryanFRD merged 5 commits into
mainfrom
fix/675-menu-keyboard-nav

Conversation

@BryanFRD

Copy link
Copy Markdown
Contributor

Closes #675

  • flr-menu focuses the first enabled item on open, handles ArrowUp/ArrowDown/Home/End, closes on Tab and returns focus to the trigger on close
  • flr-brand-dropdown is an inline list of links, so role=menu/menuitem and aria-haspopup are removed
  • Added a KeyboardNavigation play story for the menu

Not run locally: test-storybook fails to load the @swc/core native binding on this machine. Storybook builds and the showcase typechecks.

Focus the first item on open, add arrow/Home/End navigation, close on Tab and restore focus to the trigger. Drop role=menu from the inline brand dropdown, which is a plain list of links.

@ferrfleet-interne ferrfleet-interne Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The keyboard behaviour is right, and the story covers it well. One blocking finding: the roving focus reimplements CDK's FocusKeyManager (see inline). Dropping the menu/menuitem roles from brand-dropdown is the correct call while it has no keyboard support.

Comment thread packages/ui-ng/src/lib/menu/menu.component.ts
Comment thread packages/ui-ng/src/lib/menu/menu.component.ts Outdated

@ferrfleet-interne ferrfleet-interne Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Both earlier findings are fixed in 41f6956, and the threads are resolved.

Nit: withTypeAhead() does nothing as written. The FocusableOption objects built in options have no getLabel, and the key manager needs that method to match typed characters. Either add getLabel to MenuItemComponent (return the .flr-menu-item__label text through a viewChild) and map it into options, or drop withTypeAhead().

@ferrfleet-interne ferrfleet-interne Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ae9fb3a looks right: caching options per item in the WeakMap keeps the references stable, so FocusKeyManager keeps the right active item when the item list changes.

@ferrfleet-interne ferrfleet-interne Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

49b5ab3 only touches the story. Sending keyCode matches what FocusKeyManager reads. The custom keyboardMap replaces user-event's default map, but the story only presses the six keys it lists, so that is fine.

The trigger host is a custom element and not focusable. Story now dispatches keydown with keyCode, which user-event omits.

@ferrfleet-interne ferrfleet-interne Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

a41b908 looks right. onDetach now focuses the trigger itself when it can take focus, and otherwise the first focusable element inside it. That covers a custom-element host like <flr-button flr-menu-trigger>. The story's press() sets keyCode explicitly, which is what FocusKeyManager reads.

@BryanFRD
BryanFRD merged commit eb30ecb into main Oct 25, 2026
16 checks passed
@BryanFRD
BryanFRD deleted the fix/675-menu-keyboard-nav branch October 25, 2026 10:41
ferrflow Bot added a commit that referenced this pull request Oct 25, 2026
## [1.45.1] - 2026-10-25

### Bug Fixes

- fix(ui-ng): make flr-menu keyboard navigable (#679)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

fix(ui-ng): flr-menu items are not reachable from the keyboard

1 participant