Skip to content

Commit b0bbc54

Browse files
committed
fix(overlay): stop using capture phase for overlay keyboard handling
OverlayKeyboardDispatcher is a document-level keyboard listener that dispatches events to the topmost overlay that's listening for them. It does it on capture as of e30852a in order to avoid missing events whose propagation have been stopped. However, there are legitimate use cases for stopping propagation and not wanting the overlay to hear about it. For example, grid navigation based on the ARIA best practice allows for enter to trap focus inside a grid cell and escape to leave it and restore focus to the grid cell. https://www.w3.org/TR/wai-aria-practices-1.1/#gridNav_inside In these cases, we must be able to call stopPropagation and prevent the escape keypress event from reaching the overlay. Fixes #9928. BREAKING CHANGE: OverlayKeyboardDispatcher (used in dialog and overlay and available in the CDK) now listens on bubbling/propagation phase instead of capture phase. This means that overlay keydown handlers are now called after any applicable handlers inside of an overlay, and it respects any stopPropagation() calls from inside the overlay.
1 parent 94c27b5 commit b0bbc54

File tree

2 files changed

+4
-4
lines changed

2 files changed

+4
-4
lines changed

src/cdk/overlay/keyboard/overlay-keyboard-dispatcher.spec.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ describe('OverlayKeyboardDispatcher', () => {
6969
expect(overlayTwoSpy).toHaveBeenCalled();
7070
});
7171

72-
it('should dispatch keyboard events when propagation is stopped', () => {
72+
fit('should not dispatch keyboard events when propagation is stopped', () => {
7373
const overlayRef = overlay.create();
7474
const spy = jasmine.createSpy('keyboard event spy');
7575
const button = document.createElement('button');
@@ -81,7 +81,7 @@ describe('OverlayKeyboardDispatcher', () => {
8181
keyboardDispatcher.add(overlayRef);
8282
dispatchKeyboardEvent(button, 'keydown', ESCAPE);
8383

84-
expect(spy).toHaveBeenCalled();
84+
expect(spy).not.toHaveBeenCalled();
8585

8686
button.parentNode!.removeChild(button);
8787
});

src/cdk/overlay/keyboard/overlay-keyboard-dispatcher.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ export class OverlayKeyboardDispatcher implements OnDestroy {
4747

4848
// Lazily start dispatcher once first overlay is added
4949
if (!this._isAttached) {
50-
this._document.body.addEventListener('keydown', this._keydownListener, true);
50+
this._document.body.addEventListener('keydown', this._keydownListener);
5151
this._isAttached = true;
5252
}
5353

@@ -71,7 +71,7 @@ export class OverlayKeyboardDispatcher implements OnDestroy {
7171
/** Detaches the global keyboard event listener. */
7272
private _detach() {
7373
if (this._isAttached) {
74-
this._document.body.removeEventListener('keydown', this._keydownListener, true);
74+
this._document.body.removeEventListener('keydown', this._keydownListener);
7575
this._isAttached = false;
7676
}
7777
}

0 commit comments

Comments
 (0)