Skip to content

Commit 1fa6e3b

Browse files
committed
fix(material/menu): do not auto-focus when hover opens menu
1 parent f3f277a commit 1fa6e3b

File tree

3 files changed

+9
-6
lines changed

3 files changed

+9
-6
lines changed

goldens/material/menu/index.api.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -261,7 +261,7 @@ export class MatMenuTrigger implements AfterContentInit, OnDestroy {
261261
readonly onMenuOpen: EventEmitter<void>;
262262
// (undocumented)
263263
_openedBy: Exclude<FocusOrigin, 'program' | null> | undefined;
264-
openMenu(): void;
264+
openMenu(disableAutoFocus?: boolean): void;
265265
restoreFocus: boolean;
266266
toggleMenu(): void;
267267
triggersSubmenu(): boolean;

src/material/menu/menu-trigger.ts

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -282,7 +282,7 @@ export class MatMenuTrigger implements AfterContentInit, OnDestroy {
282282
}
283283

284284
/** Opens the menu. */
285-
openMenu(): void {
285+
openMenu(disableAutoFocus?: boolean): void {
286286
const menu = this.menu;
287287

288288
if (this._menuOpen || !menu) {
@@ -317,7 +317,7 @@ export class MatMenuTrigger implements AfterContentInit, OnDestroy {
317317
this._closingActionsSubscription = this._menuClosingActions().subscribe(() => this.closeMenu());
318318
menu.parentMenu = this.triggersSubmenu() ? this._parentMaterialMenu : undefined;
319319
menu.direction = this.dir;
320-
menu.focusFirstItem(this._openedBy || 'program');
320+
if (!disableAutoFocus) menu.focusFirstItem(this._openedBy || 'program');
321321
this._setIsMenuOpen(true);
322322

323323
if (menu instanceof MatMenu) {
@@ -590,7 +590,10 @@ export class MatMenuTrigger implements AfterContentInit, OnDestroy {
590590
this._hoverSubscription = this._parentMaterialMenu._hovered().subscribe(active => {
591591
if (active === this._menuItemInstance && !active.disabled) {
592592
this._openedBy = 'mouse';
593-
this.openMenu();
593+
// Open the menu, but do NOT auto-focus on first item when just hovering.
594+
// When VoiceOver is enabled, this is particularly confusing as the focus will
595+
// cause another hover event, and continue opening sub-menus without interaction.
596+
this.openMenu(true);
594597
}
595598
});
596599
}

src/material/menu/menu.spec.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2510,7 +2510,7 @@ describe('MatMenu', () => {
25102510
}),
25112511
);
25122512

2513-
it('should not re-focus a child menu trigger when hovering another trigger', fakeAsync(() => {
2513+
it('should preserve focus on a child menu trigger when hovering another trigger', fakeAsync(() => {
25142514
dispatchFakeEvent(instance.rootTriggerEl.nativeElement, 'mousedown');
25152515
instance.rootTriggerEl.nativeElement.click();
25162516
fixture.detectChanges();
@@ -2529,7 +2529,7 @@ describe('MatMenu', () => {
25292529
fixture.detectChanges();
25302530
tick(500);
25312531

2532-
expect(document.activeElement).not.toBe(
2532+
expect(document.activeElement).toBe(
25332533
levelOneTrigger,
25342534
'Expected focus not to be returned to the initial trigger.',
25352535
);

0 commit comments

Comments
 (0)