Skip to content

Commit 0b4fe40

Browse files
committed
fix(menu): not handling keyboard events when opened by mouse
Fixes the menu keyboard interactions not working when it is opened by a click. Fixes #4991.
1 parent 38b365c commit 0b4fe40

File tree

4 files changed

+29
-6
lines changed

4 files changed

+29
-6
lines changed

src/lib/menu/menu-trigger.ts

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -163,10 +163,15 @@ export class MdMenuTrigger implements AfterViewInit, OnDestroy {
163163
private _initMenu(): void {
164164
this._setIsMenuOpen(true);
165165

166-
// Should only set focus if opened via the keyboard, so keyboard users can
167-
// can easily navigate menu items. According to spec, mouse users should not
168-
// see the focus style.
169-
if (!this._openedByMouse) {
166+
// If the menu was opened by mouse, we focus the root node, which allows for the keyboard
167+
// interactions to work. Otherwise, if the menu was opened by keyboard, we focus the first item.
168+
if (this._openedByMouse) {
169+
let rootNode = this._overlayRef.overlayElement.firstElementChild as HTMLElement;
170+
171+
if (rootNode) {
172+
rootNode.focus();
173+
}
174+
} else {
170175
this.menu.focusFirstItem();
171176
}
172177
}

src/lib/menu/menu.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<ng-template>
22
<div class="mat-menu-panel" [ngClass]="_classList" (keydown)="_handleKeydown($event)"
3-
(click)="_emitCloseEvent()" [@transformMenu]="'showing'" role="menu">
3+
(click)="_emitCloseEvent()" [@transformMenu]="'showing'" role="menu" tabindex="-1">
44
<div class="mat-menu-content" [@fadeInItems]="'showing'">
55
<ng-content></ng-content>
66
</div>

src/lib/menu/menu.scss

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ $mat-menu-vertical-padding: 8px !default;
1212
@include mat-menu-base();
1313
@include mat-menu-positions();
1414
max-height: calc(100vh - #{$mat-menu-item-height});
15+
outline: 0;
1516

1617
@include cdk-high-contrast {
1718
outline: solid 1px;

src/lib/menu/menu.spec.ts

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ import {OverlayContainer} from '../core/overlay/overlay-container';
2121
import {Directionality, Direction} from '../core/bidi/index';
2222
import {extendObject} from '../core/util/object-extend';
2323
import {ESCAPE} from '../core/keyboard/keycodes';
24-
import {dispatchKeyboardEvent} from '../core/testing/dispatch-events';
24+
import {dispatchKeyboardEvent, dispatchFakeEvent} from '../core/testing/dispatch-events';
2525

2626

2727
describe('MdMenu', () => {
@@ -146,6 +146,23 @@ describe('MdMenu', () => {
146146
expect(role).toBe('menu', 'Expected panel to have the "menu" role.');
147147
});
148148

149+
it('should focus the menu panel root node when it was opened by mouse', () => {
150+
const fixture = TestBed.createComponent(SimpleMenu);
151+
152+
fixture.detectChanges();
153+
154+
const triggerEl = fixture.componentInstance.triggerEl.nativeElement;
155+
156+
dispatchFakeEvent(triggerEl, 'mousedown');
157+
triggerEl.click();
158+
fixture.detectChanges();
159+
160+
const panel = overlayContainerElement.querySelector('.mat-menu-panel');
161+
162+
expect(panel).toBeTruthy('Expected the panel to be rendered.');
163+
expect(document.activeElement).toBe(panel, 'Expected the panel to be focused.');
164+
});
165+
149166
describe('positions', () => {
150167
let fixture: ComponentFixture<PositionedMenu>;
151168
let panel: HTMLElement;

0 commit comments

Comments
 (0)