Skip to content

Commit a5cc967

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 0aaeb69 commit a5cc967

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
@@ -161,10 +161,15 @@ export class MdMenuTrigger implements AfterViewInit, OnDestroy {
161161
private _initMenu(): void {
162162
this._setIsMenuOpen(true);
163163

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

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'">
3+
(click)="_emitCloseEvent()" [@transformMenu]="'showing'" 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 {Dir, LayoutDirection} from '../core/rtl/dir';
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', () => {
@@ -134,6 +134,23 @@ describe('MdMenu', () => {
134134
expect(panel.classList).toContain('custom-two');
135135
});
136136

137+
it('should focus the menu panel root node when it was opened by mouse', () => {
138+
const fixture = TestBed.createComponent(SimpleMenu);
139+
140+
fixture.detectChanges();
141+
142+
const triggerEl = fixture.componentInstance.triggerEl.nativeElement;
143+
144+
dispatchFakeEvent(triggerEl, 'mousedown');
145+
triggerEl.click();
146+
fixture.detectChanges();
147+
148+
const panel = overlayContainerElement.querySelector('.mat-menu-panel');
149+
150+
expect(panel).toBeTruthy('Expected the panel to be rendered.');
151+
expect(document.activeElement).toBe(panel, 'Expected the panel to be focused.');
152+
});
153+
137154
describe('positions', () => {
138155
let fixture: ComponentFixture<PositionedMenu>;
139156
let panel: HTMLElement;

0 commit comments

Comments
 (0)