Skip to content

Commit 5c4da31

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

File tree

2 files changed

+13
-4
lines changed

2 files changed

+13
-4
lines changed

src/material/menu/menu-trigger.ts

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -283,6 +283,12 @@ export class MatMenuTrigger implements AfterContentInit, OnDestroy {
283283

284284
/** Opens the menu. */
285285
openMenu(): void {
286+
// Auto focus by default
287+
this._openMenu(true);
288+
}
289+
290+
/** Internal method to open menu providing option to auto focus on first item. */
291+
private _openMenu(autoFocus: boolean): void {
286292
const menu = this.menu;
287293

288294
if (this._menuOpen || !menu) {
@@ -317,7 +323,7 @@ export class MatMenuTrigger implements AfterContentInit, OnDestroy {
317323
this._closingActionsSubscription = this._menuClosingActions().subscribe(() => this.closeMenu());
318324
menu.parentMenu = this.triggersSubmenu() ? this._parentMaterialMenu : undefined;
319325
menu.direction = this.dir;
320-
menu.focusFirstItem(this._openedBy || 'program');
326+
if (autoFocus) menu.focusFirstItem(this._openedBy || 'program');
321327
this._setIsMenuOpen(true);
322328

323329
if (menu instanceof MatMenu) {
@@ -590,7 +596,10 @@ export class MatMenuTrigger implements AfterContentInit, OnDestroy {
590596
this._hoverSubscription = this._parentMaterialMenu._hovered().subscribe(active => {
591597
if (active === this._menuItemInstance && !active.disabled) {
592598
this._openedBy = 'mouse';
593-
this.openMenu();
599+
// Open the menu, but do NOT auto-focus on first item when just hovering.
600+
// When VoiceOver is enabled, this is particularly confusing as the focus will
601+
// cause another hover event, and continue opening sub-menus without interaction.
602+
this._openMenu(false);
594603
}
595604
});
596605
}

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)