Skip to content

Commit cc5f7d0

Browse files
committed
fix(cdk/menu): move focus when opening via click (#26874)
Fixes that the CDK menu wasn't moving focus to the first item when opening using a click. This caused other issues like not being able to use the escape key to close the menu. Fixes #26858. (cherry picked from commit 5825d4a)
1 parent 9334fd6 commit cc5f7d0

File tree

4 files changed

+30
-3
lines changed

4 files changed

+30
-3
lines changed

src/cdk/menu/menu-bar.spec.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1037,11 +1037,11 @@ describe('MenuBar', () => {
10371037

10381038
dispatchKeyboardEvent(nativeMenus[0], 'keydown', DOWN_ARROW);
10391039
detectChanges();
1040-
expect(document.activeElement).toEqual(fileMenuNativeItems[0]);
1040+
expect(document.activeElement).toEqual(fileMenuNativeItems[1]);
10411041

10421042
dispatchKeyboardEvent(nativeMenus[0], 'keydown', DOWN_ARROW);
10431043
detectChanges();
1044-
expect(document.activeElement).toEqual(fileMenuNativeItems[1]);
1044+
expect(document.activeElement).toEqual(fileMenuNativeItems[2]);
10451045
});
10461046

10471047
it(

src/cdk/menu/menu-trigger.spec.ts

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import {Component, ViewChildren, QueryList, ElementRef, ViewChild, Type} from '@angular/core';
2-
import {ComponentFixture, TestBed, waitForAsync} from '@angular/core/testing';
2+
import {ComponentFixture, TestBed, fakeAsync, tick, waitForAsync} from '@angular/core/testing';
33
import {By} from '@angular/platform-browser';
44
import {dispatchKeyboardEvent} from '../../cdk/testing/private';
55
import {TAB, SPACE, ENTER} from '@angular/cdk/keycodes';
@@ -539,6 +539,26 @@ describe('MenuTrigger', () => {
539539
expect(fixture.componentInstance.trigger.isOpen()).toBeFalse();
540540
});
541541
});
542+
543+
it('should focus the first item when opening on click', fakeAsync(() => {
544+
TestBed.configureTestingModule({
545+
imports: [CdkMenuModule],
546+
declarations: [TriggersWithSameMenuDifferentMenuBars],
547+
}).compileComponents();
548+
549+
const fixture = TestBed.createComponent(TriggersWithSameMenuDifferentMenuBars);
550+
fixture.detectChanges();
551+
552+
fixture.componentInstance.nativeTriggers.first.nativeElement.click();
553+
fixture.detectChanges();
554+
tick();
555+
556+
const firstItem =
557+
fixture.componentInstance.nativeMenus.first.nativeElement.querySelector('.cdk-menu-item');
558+
559+
expect(firstItem).toBeTruthy();
560+
expect(document.activeElement).toBe(firstItem);
561+
}));
542562
});
543563

544564
@Component({
@@ -599,7 +619,10 @@ class MenuBarWithNestedSubMenus {
599619
})
600620
class TriggersWithSameMenuDifferentMenuBars {
601621
@ViewChildren(CdkMenuTrigger) triggers: QueryList<CdkMenuTrigger>;
622+
@ViewChildren(CdkMenuTrigger, {read: ElementRef}) nativeTriggers: QueryList<ElementRef>;
623+
602624
@ViewChildren(CdkMenu) menus: QueryList<CdkMenu>;
625+
@ViewChildren(CdkMenu, {read: ElementRef}) nativeMenus: QueryList<ElementRef>;
603626
}
604627

605628
@Component({

src/cdk/menu/menu-trigger.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,7 @@ export class CdkMenuTrigger extends CdkMenuTriggerBase implements OnDestroy {
177177
// already do the same on `keydown` events for enter and space.
178178
if (this._inputModalityDetector.mostRecentModality !== 'keyboard') {
179179
this.toggle();
180+
this.childMenu?.focusFirstItem('mouse');
180181
}
181182
}
182183

src/cdk/menu/menu.spec.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -447,6 +447,7 @@ describe('Menu', () => {
447447
it('should close the edit menu when hovering directly up from the edit menu trigger to the print item without waiting', fakeAsync(() => {
448448
openFileMenu();
449449
openMenuOnHover(nativeEditTrigger!);
450+
tick();
450451

451452
const editPosition = nativeEditTrigger!.getBoundingClientRect();
452453
const printPosition = nativeFileButtons![0].getBoundingClientRect();
@@ -490,6 +491,8 @@ describe('Menu', () => {
490491
it('should not close the edit submenu when hovering into its items in time', fakeAsync(() => {
491492
openFileMenu();
492493
openMenuOnHover(nativeEditTrigger!);
494+
tick();
495+
493496
const editPosition = nativeEditTrigger!.getBoundingClientRect();
494497
const undoPosition = nativeEditButtons![0].getBoundingClientRect();
495498

0 commit comments

Comments
 (0)