Skip to content

Commit e373721

Browse files
crisbetozarend
authored andcommitted
fix(material/menu): not interrupting keyboard events to other overlays (#22928)
This is a resubmit of #22856 which had some issues in g3. For historical reasons, `mat-menu` doesn't use the same keyboard event dispatcher as the other overlays. To work around it, previously we added a dummy subscription so that the menu would still show up in the overlay keyboard stack. This works for most events, but it breaks down for the escape key, because closing the menu removes it from the stack immediately, allowing the event to bubble up to the document and be dispatched to the next overlay in the stack. These changes resolve the issue by adding a stopPropagation call. Fixes #22694. (cherry picked from commit 5f529db)
1 parent 6c87852 commit e373721

File tree

3 files changed

+9
-0
lines changed

3 files changed

+9
-0
lines changed

src/material-experimental/mdc-menu/menu.spec.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -439,13 +439,15 @@ describe('MDC-based MatMenu', () => {
439439

440440
const panel = overlayContainerElement.querySelector('.mat-mdc-menu-panel')!;
441441
const event = createKeyboardEvent('keydown', ESCAPE);
442+
spyOn(event, 'stopPropagation').and.callThrough();
442443

443444
dispatchEvent(panel, event);
444445
fixture.detectChanges();
445446
tick(500);
446447

447448
expect(overlayContainerElement.textContent).toBe('');
448449
expect(event.defaultPrevented).toBe(true);
450+
expect(event.stopPropagation).toHaveBeenCalled();
449451
}));
450452

451453
it('should not close the menu when pressing ESCAPE with a modifier', fakeAsync(() => {

src/material/menu/menu.spec.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -440,13 +440,15 @@ describe('MatMenu', () => {
440440

441441
const panel = overlayContainerElement.querySelector('.mat-menu-panel')!;
442442
const event = createKeyboardEvent('keydown', ESCAPE);
443+
spyOn(event, 'stopPropagation').and.callThrough();
443444

444445
dispatchEvent(panel, event);
445446
fixture.detectChanges();
446447
tick(500);
447448

448449
expect(overlayContainerElement.textContent).toBe('');
449450
expect(event.defaultPrevented).toBe(true);
451+
expect(event.stopPropagation).toHaveBeenCalled();
450452
}));
451453

452454
it('should not close the menu when pressing ESCAPE with a modifier', fakeAsync(() => {

src/material/menu/menu.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -337,7 +337,12 @@ export class _MatMenuBase implements AfterContentInit, MatMenuPanel<MatMenuItem>
337337
}
338338

339339
manager.onKeydown(event);
340+
return;
340341
}
342+
343+
// Don't allow the event to propagate if we've already handled it, or it may
344+
// end up reaching other overlays that were opened earlier (see #22694).
345+
event.stopPropagation();
341346
}
342347

343348
/**

0 commit comments

Comments
 (0)