Repository navigation
Conversation
Pressing down outside of a menu opened by a standalone trigger moves focus away from the menu, which closed it right away on mousedown. This doesn't allow users to cancel the action by moving the pointer back before releasing it (WCAG 2.5.2 Pointer Cancellation). When focus leaves the menu because of a press outside of it, wait for the press to be released and only close the menu if it's released outside as well. Focus moving away by other means (e.g. the keyboard) still closes the menu immediately. Fixes angular#27878
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #27878
With a standalone
cdkMenuTriggerFor, pressing down anywhere outside the open menu closes it immediately, before the button is released. As noted in the issue, the outside click listener never gets a chance: the mousedown blurs the menu,menuStack.hasFocusemitsfalseandCdkMenuTriggercallscloseAll(). That means the close can't be cancelled by moving the pointer away before releasing (WCAG 2.5.2 Pointer Cancellation), and it's different from the menu bar andmat-menu.I didn't remove the
hasFocuslistener, because it's also what closes the menu when focus leaves it from the keyboard (Tab, or focus moving somewhere else programmatically). Instead, while a root menu is open the trigger now tracks pointer presses on the document:pointerdownoutside of the trigger and the menu stack marks that a press is in progress.pointerup.pointerupthe menu closes if the pointer was released outside, and stays open if it was moved back onto the menu.pointercanceland closing the menu reset the state, and the listeners are only attached while the menu is open.I listen on the document rather than relying on the overlay's outside click events. A press on the empty area below a short page lands on
<html>, which the outside click dispatcher (attached tobody) doesn't see, and the menu would stay open after the release. Focus loss that isn't caused by a press closes the menu right away, the same as before.Tests
New specs in
menu-trigger.spec.ts(standalone trigger):pointerupoutside closes itpointerupon the menu keeps it openWithout the change in
menu-trigger.ts, the two press specs fail (Expected 1 to be 2.).Manual check
Standalone trigger +
cdkMenuwith a nested submenu, CDK 22.2.6 and then the same build with this change. I drove it with Playwright using real mouse events, holding the button for 500ms on the page background:Before, while the mouse button is still held down outside the menu:
After: