Skip to content

fix(cdk/menu): keep menu open when selectable button item is toggled with space - #34087

Open
prath47 wants to merge 1 commit into
angular:mainfrom
prath47:cdk-menu-space-keep-open
Open

prath47 wants to merge 1 commit into
angular:mainfrom
prath47:cdk-menu-space-keep-open

Conversation

@prath47

@prath47 prath47 commented Nov 6, 2026

Copy link
Copy Markdown

Fixes #27818

CdkMenuItemSelectable sets closeOnSpacebarTrigger = false so checkbox/radio items keep the menu open when toggled with Space. That only kicks in on the keydown path, though. For a native <button> (which is what the docs examples use), _onKeydown skips Space/Enter because eventDispatchesNativeClick says the browser will dispatch a click. That click then goes through _handleClick → trigger() with no keepOpen, so the menu closes anyway.

The keydown handler now stores whether that key should keep the menu open before letting the native click through, and _handleClick uses it for the click that follows. I only honour it for clicks with detail === 0 (what the browser dispatches for keyboard activation), so a stale flag can't make a later mouse click keep the menu open. The flag is reset after every click.

Nothing changes for non-native items (they never got the native click and already used keepOpen), for Enter, or for mouse clicks.

Tests

Unit tests can't produce a trusted keydown, so the new specs call _onKeydown with a trusted-looking event and then dispatch a detail: 0 click, the same sequence the browser produces:

  • checkbox: Space keeps the menu open, Enter closes it, and a mouse click after a Space keydown still closes it
  • radio: Space keeps the menu open
bazel test //src/cdk/menu:unit_tests

//src/cdk/menu:unit_tests_chromium      PASSED
//src/cdk/menu:unit_tests_firefox       PASSED

Without the menu-item.ts change, both Space specs fail with Expected spy closeAll not to have been called.

Manual check

I also checked with real key presses through Playwright, using a cdkMenuTriggerFor menu with <button cdkMenuItemCheckbox> / <button cdkMenuItemRadio> items like the docs example (CDK 22.2.6, then the same build with this change). Steps: open the menu with Enter, ArrowDown to "Italic", press Space.

before after
Chromium 156 menu closed, focus back on trigger menu open, focus on Italic
Firefox 157 menu closed menu open
WebKit 27.2 menu closed menu open

In all three, Italic gets toggled either way. With the change, Enter on an item and a mouse click on an item still close the menu.

Before:

before

After:

after

…with space

Checkbox and radio menu items are meant to keep the menu open when they're
toggled with the space key. That only worked for non-native elements. For
a native button, the keydown handler skips the event because the browser
dispatches a click for it, and the click handler then triggered the item
without keepOpen, closing the menu.

Remember whether the keydown should keep the menu open and use it for the
click the browser dispatches for that key. Mouse clicks still close the
menu as before.

Fixes angular#27818

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

bug(CdkMenu): Selectable menu items (radio/checkbox) don't stay open when spacebar used

1 participant