Skip to content

Commit

Permalink
fix(cdk/menu): move focus when opening via click (#26874)
Browse files Browse the repository at this point in the history
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)
  • Loading branch information
crisbeto committed Apr 3, 2023
1 parent 9334fd6 commit cc5f7d0
Show file tree
Hide file tree
Showing 4 changed files with 30 additions and 3 deletions.
4 changes: 2 additions & 2 deletions src/cdk/menu/menu-bar.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1037,11 +1037,11 @@ describe('MenuBar', () => {

dispatchKeyboardEvent(nativeMenus[0], 'keydown', DOWN_ARROW);
detectChanges();
expect(document.activeElement).toEqual(fileMenuNativeItems[0]);
expect(document.activeElement).toEqual(fileMenuNativeItems[1]);

dispatchKeyboardEvent(nativeMenus[0], 'keydown', DOWN_ARROW);
detectChanges();
expect(document.activeElement).toEqual(fileMenuNativeItems[1]);
expect(document.activeElement).toEqual(fileMenuNativeItems[2]);
});

it(
Expand Down
25 changes: 24 additions & 1 deletion src/cdk/menu/menu-trigger.spec.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import {Component, ViewChildren, QueryList, ElementRef, ViewChild, Type} from '@angular/core';
import {ComponentFixture, TestBed, waitForAsync} from '@angular/core/testing';
import {ComponentFixture, TestBed, fakeAsync, tick, waitForAsync} from '@angular/core/testing';
import {By} from '@angular/platform-browser';
import {dispatchKeyboardEvent} from '../../cdk/testing/private';
import {TAB, SPACE, ENTER} from '@angular/cdk/keycodes';
Expand Down Expand Up @@ -539,6 +539,26 @@ describe('MenuTrigger', () => {
expect(fixture.componentInstance.trigger.isOpen()).toBeFalse();
});
});

it('should focus the first item when opening on click', fakeAsync(() => {
TestBed.configureTestingModule({
imports: [CdkMenuModule],
declarations: [TriggersWithSameMenuDifferentMenuBars],
}).compileComponents();

const fixture = TestBed.createComponent(TriggersWithSameMenuDifferentMenuBars);
fixture.detectChanges();

fixture.componentInstance.nativeTriggers.first.nativeElement.click();
fixture.detectChanges();
tick();

const firstItem =
fixture.componentInstance.nativeMenus.first.nativeElement.querySelector('.cdk-menu-item');

expect(firstItem).toBeTruthy();
expect(document.activeElement).toBe(firstItem);
}));
});

@Component({
Expand Down Expand Up @@ -599,7 +619,10 @@ class MenuBarWithNestedSubMenus {
})
class TriggersWithSameMenuDifferentMenuBars {
@ViewChildren(CdkMenuTrigger) triggers: QueryList<CdkMenuTrigger>;
@ViewChildren(CdkMenuTrigger, {read: ElementRef}) nativeTriggers: QueryList<ElementRef>;

@ViewChildren(CdkMenu) menus: QueryList<CdkMenu>;
@ViewChildren(CdkMenu, {read: ElementRef}) nativeMenus: QueryList<ElementRef>;
}

@Component({
Expand Down
1 change: 1 addition & 0 deletions src/cdk/menu/menu-trigger.ts
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,7 @@ export class CdkMenuTrigger extends CdkMenuTriggerBase implements OnDestroy {
// already do the same on `keydown` events for enter and space.
if (this._inputModalityDetector.mostRecentModality !== 'keyboard') {
this.toggle();
this.childMenu?.focusFirstItem('mouse');
}
}

Expand Down
3 changes: 3 additions & 0 deletions src/cdk/menu/menu.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -447,6 +447,7 @@ describe('Menu', () => {
it('should close the edit menu when hovering directly up from the edit menu trigger to the print item without waiting', fakeAsync(() => {
openFileMenu();
openMenuOnHover(nativeEditTrigger!);
tick();

const editPosition = nativeEditTrigger!.getBoundingClientRect();
const printPosition = nativeFileButtons![0].getBoundingClientRect();
Expand Down Expand Up @@ -490,6 +491,8 @@ describe('Menu', () => {
it('should not close the edit submenu when hovering into its items in time', fakeAsync(() => {
openFileMenu();
openMenuOnHover(nativeEditTrigger!);
tick();

const editPosition = nativeEditTrigger!.getBoundingClientRect();
const undoPosition = nativeEditButtons![0].getBoundingClientRect();

Expand Down

0 comments on commit cc5f7d0

Please sign in to comment.