Skip to content

Commit 730e6a3

Browse files
crisbetovivian-hu-zz
authored andcommitted
fix(menu): incorrectly styling keyboard focus, if trigger is right clicked before opening (#13136)
Currently `mat-menu` displays focus indication only if it has been opened by keyboard. We detect how the menu was opened using a `mousedown` event. The issue comes from the fact that `mousedown` also fires for right or middle button clicks, event though a subsequent `click` won't fire, which will throw off our detection if the user opens the menu with their keyboard afterwards. These changes add a check that ensures that only left button clicks are considered as opening.
1 parent ff23527 commit 730e6a3

File tree

2 files changed

+30
-3
lines changed

2 files changed

+30
-3
lines changed

src/lib/menu/menu-trigger.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -454,7 +454,9 @@ export class MatMenuTrigger implements AfterContentInit, OnDestroy {
454454
/** Handles mouse presses on the trigger. */
455455
_handleMousedown(event: MouseEvent): void {
456456
if (!isFakeMousedownFromScreenReader(event)) {
457-
this._openedByMouse = true;
457+
// Since right or middle button clicks won't trigger the `click` event,
458+
// we shouldn't consider the menu as opened by mouse in those cases.
459+
this._openedByMouse = event.button === 0;
458460

459461
// Since clicking on the trigger won't close the menu if it opens a sub-menu,
460462
// we should prevent focus from moving onto it via click to avoid the

src/lib/menu/menu.spec.ts

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -208,7 +208,7 @@ describe('MatMenu', () => {
208208
fixture.detectChanges();
209209
const triggerEl = fixture.componentInstance.triggerEl.nativeElement;
210210

211-
dispatchFakeEvent(triggerEl, 'mousedown');
211+
dispatchMouseEvent(triggerEl, 'mousedown');
212212
triggerEl.click();
213213
fixture.detectChanges();
214214
patchElementFocus(triggerEl);
@@ -222,6 +222,31 @@ describe('MatMenu', () => {
222222
focusMonitor.stopMonitoring(triggerEl);
223223
}));
224224

225+
it('should set proper focus origin when right clicking on trigger, before opening by keyboard',
226+
fakeAsync(() => {
227+
const fixture = createComponent(SimpleMenu, [], [FakeIcon]);
228+
fixture.detectChanges();
229+
const triggerEl = fixture.componentInstance.triggerEl.nativeElement;
230+
231+
patchElementFocus(triggerEl);
232+
focusMonitor.monitor(triggerEl, false);
233+
234+
// Trigger a fake right click.
235+
dispatchEvent(triggerEl, createMouseEvent('mousedown', 50, 100, 2));
236+
237+
// A click without a left button mousedown before it is considered a keyboard open.
238+
triggerEl.click();
239+
fixture.detectChanges();
240+
241+
fixture.componentInstance.trigger.closeMenu();
242+
fixture.detectChanges();
243+
tick(500);
244+
fixture.detectChanges();
245+
246+
expect(triggerEl.classList).toContain('cdk-program-focused');
247+
focusMonitor.stopMonitoring(triggerEl);
248+
}));
249+
225250
it('should close the menu when pressing ESCAPE', fakeAsync(() => {
226251
const fixture = createComponent(SimpleMenu, [], [FakeIcon]);
227252
fixture.detectChanges();
@@ -347,7 +372,7 @@ describe('MatMenu', () => {
347372

348373
const triggerEl = fixture.componentInstance.triggerEl.nativeElement;
349374

350-
dispatchFakeEvent(triggerEl, 'mousedown');
375+
dispatchMouseEvent(triggerEl, 'mousedown');
351376
triggerEl.click();
352377
fixture.detectChanges();
353378
tick(500);

0 commit comments

Comments
 (0)