Skip to content

Commit 3b6c40d

Browse files
committed
fix(select): Improve the a11y of select component by making overlay
always exist in the DOM
1 parent 48dda50 commit 3b6c40d

File tree

5 files changed

+154
-29
lines changed

5 files changed

+154
-29
lines changed

src/cdk/overlay/overlay-directives.spec.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,18 @@ describe('Overlay directives', () => {
120120
'Expected overlay to have been detached.');
121121
});
122122

123+
it('should not close when pressing escape when changed the setting of "detachOnEscape"', () => {
124+
fixture.componentInstance.isOpen = true;
125+
fixture.componentInstance.detachOnEscape = false;
126+
fixture.detectChanges();
127+
128+
dispatchKeyboardEvent(document.body, 'keydown', ESCAPE);
129+
fixture.detectChanges();
130+
131+
expect(overlayContainerElement.textContent!.trim()).not.toBe('',
132+
'Expected overlay to have not been detached.');
133+
});
134+
123135
it('should not depend on the order in which the `origin` and `open` are set', async(() => {
124136
fixture.destroy();
125137

@@ -467,6 +479,7 @@ describe('Overlay directives', () => {
467479
[cdkConnectedOverlayFlexibleDimensions]="flexibleDimensions"
468480
[cdkConnectedOverlayGrowAfterOpen]="growAfterOpen"
469481
[cdkConnectedOverlayPush]="push"
482+
[cdkConnectedOverlayDetachOnEscape]="detachOnEscape"
470483
cdkConnectedOverlayBackdropClass="mat-test-class"
471484
(backdropClick)="backdropClickHandler($event)"
472485
[cdkConnectedOverlayOffsetX]="offsetX"
@@ -498,6 +511,7 @@ class ConnectedOverlayDirectiveTest {
498511
flexibleDimensions: boolean;
499512
growAfterOpen: boolean;
500513
push: boolean;
514+
detachOnEscape: boolean = true;
501515
backdropClickHandler = jasmine.createSpy('backdropClick handler');
502516
positionChangeHandler = jasmine.createSpy('positionChangeHandler');
503517
positionOverrides: ConnectionPositionPair[];

src/cdk/overlay/overlay-directives.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,9 @@ export class CdkConnectedOverlay implements OnDestroy, OnChanges {
165165
@Input('cdkConnectedOverlayScrollStrategy') scrollStrategy: ScrollStrategy =
166166
this._scrollStrategy();
167167

168+
/** Strategy to detach the overlay panel on ESCAPE keydown */
169+
@Input('cdkConnectedOverlayDetachOnEscape') detachOnEscape: boolean = true;
170+
168171
/** Whether the overlay is open. */
169172
@Input('cdkConnectedOverlayOpen') open: boolean = false;
170173

@@ -335,7 +338,7 @@ export class CdkConnectedOverlay implements OnDestroy, OnChanges {
335338
this._createOverlay();
336339

337340
this._overlayRef!.keydownEvents().subscribe((event: KeyboardEvent) => {
338-
if (event.keyCode === ESCAPE) {
341+
if (this.detachOnEscape && event.keyCode === ESCAPE) {
339342
this._detachOverlay();
340343
}
341344
});

src/lib/select/select.html

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,31 +19,31 @@
1919
cdk-connected-overlay
2020
cdkConnectedOverlayLockPosition
2121
cdkConnectedOverlayHasBackdrop
22+
[cdkConnectedOverlayOpen]="true"
2223
cdkConnectedOverlayBackdropClass="cdk-overlay-transparent-backdrop"
2324
[cdkConnectedOverlayScrollStrategy]="_scrollStrategy"
2425
[cdkConnectedOverlayOrigin]="origin"
25-
[cdkConnectedOverlayOpen]="panelOpen"
2626
[cdkConnectedOverlayPositions]="_positions"
2727
[cdkConnectedOverlayMinWidth]="_triggerRect?.width"
2828
[cdkConnectedOverlayOffsetY]="_offsetY"
29+
[cdkConnectedOverlayDetachOnEscape]="false"
2930
(backdropClick)="close()"
3031
(attach)="_onAttached()"
3132
(detach)="close()">
32-
3333
<div
3434
#panel
3535
class="mat-select-panel {{ _getPanelTheme() }}"
36+
[class.cdk-visually-hidden]="!panelOpen"
3637
[ngClass]="panelClass"
37-
[@transformPanel]="multiple ? 'showing-multiple' : 'showing'"
38+
[@transformPanel]="panelOpen ? (multiple ? 'showing-multiple' : 'showing') : 'void'"
3839
(@transformPanel.done)="_panelDoneAnimatingStream.next($event.toState)"
3940
[style.transformOrigin]="_transformOrigin"
4041
[class.mat-select-panel-done-animating]="_panelDoneAnimating"
4142
[style.font-size.px]="_triggerFontSize"
4243
(keydown)="_handleKeydown($event)">
43-
4444
<div
4545
class="mat-select-content"
46-
[@fadeInContent]="'showing'"
46+
[@fadeInContent]="panelOpen ? 'showing' : 'void'"
4747
(@fadeInContent.done)="_onFadeInDone()">
4848
<ng-content></ng-content>
4949
</div>

0 commit comments

Comments
 (0)