Skip to content

Commit ea31bca

Browse files
crisbetojelbourn
authored andcommitted
fix(experimental/dialog): not moving focus to container if autoFocus is disabled and focus was moved while animating (#16446)
These changes incorporate #16297 and #16221 into the experimental dialog since it follows a similar focus capturing behavior to `MatDialogContainer`. They ensure that focus is on the dialog container container when the animation is over, because it could've moved while we were animating. It also has an extra check to ensure that we don't move focus unnecessarily if the consumer decided to move focus themselves somewhere within the container.
1 parent 50292b7 commit ea31bca

File tree

1 file changed

+15
-2
lines changed

1 file changed

+15
-2
lines changed

src/cdk-experimental/dialog/dialog-container.ts

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ export class CdkDialogContainer extends BasePortalOutlet implements OnDestroy {
8080
private _elementFocusedBeforeDialogWasOpened: HTMLElement | null = null;
8181

8282
/** The class that traps and manages focus within the dialog. */
83-
private _focusTrap = this._focusTrapFactory.create(this._elementRef.nativeElement, false);
83+
private _focusTrap = this._focusTrapFactory.create(this._elementRef.nativeElement);
8484

8585
// @HostBinding is used in the class as it is expected to be extended. Since @Component decorator
8686
// metadata is not inherited by child classes, instead the host binding data is defined in a way
@@ -216,6 +216,8 @@ export class CdkDialogContainer extends BasePortalOutlet implements OnDestroy {
216216
* focus the dialog instead.
217217
*/
218218
private _autoFocusFirstTabbableElement() {
219+
const element = this._elementRef.nativeElement;
220+
219221
// If were to attempt to focus immediately, then the content of the dialog would not yet be
220222
// ready in instances where change detection has to run first. To deal with this, we simply
221223
// wait for the microtask queue to be empty.
@@ -224,9 +226,20 @@ export class CdkDialogContainer extends BasePortalOutlet implements OnDestroy {
224226
// If we didn't find any focusable elements inside the dialog, focus the
225227
// container so the user can't tab into other elements behind it.
226228
if (!hasMovedFocus) {
227-
this._elementRef.nativeElement.focus();
229+
element.focus();
228230
}
229231
});
232+
} else {
233+
const activeElement = this._document.activeElement;
234+
235+
// Otherwise ensure that focus is on the dialog container. It's possible that a different
236+
// component tried to move focus while the open animation was running. See:
237+
// https://github.com/angular/components/issues/16215. Note that we only want to do this
238+
// if the focus isn't inside the dialog already, because it's possible that the consumer
239+
// turned off `autoFocus` in order to move focus themselves.
240+
if (activeElement !== element && !element.contains(activeElement)) {
241+
element.focus();
242+
}
230243
}
231244
}
232245

0 commit comments

Comments
 (0)