@@ -21,6 +21,7 @@ import {of as observableOf, Observable, Subject, defer} from 'rxjs';
21
21
import { DialogRef } from './dialog-ref' ;
22
22
import { DialogConfig } from './dialog-config' ;
23
23
import { Directionality } from '@angular/cdk/bidi' ;
24
+ import { _supportsInert } from '@angular/cdk/platform' ;
24
25
import {
25
26
ComponentType ,
26
27
Overlay ,
@@ -47,7 +48,7 @@ export class Dialog implements OnDestroy {
47
48
private _openDialogsAtThisLevel : DialogRef < any , any > [ ] = [ ] ;
48
49
private readonly _afterAllClosedAtThisLevel = new Subject < void > ( ) ;
49
50
private readonly _afterOpenedAtThisLevel = new Subject < DialogRef > ( ) ;
50
- private _ariaHiddenElements = new Map < Element , string | null > ( ) ;
51
+ private _inertElements = new Map < Element , [ ariaHidden : string | null , inert : string | null ] > ( ) ;
51
52
private _scrollStrategy = inject ( DIALOG_SCROLL_STRATEGY ) ;
52
53
53
54
/** Keeps track of the currently-open dialogs. */
@@ -158,7 +159,7 @@ export class Dialog implements OnDestroy {
158
159
ngOnDestroy ( ) {
159
160
// Make one pass over all the dialogs that need to be untracked, but should not be closed. We
160
161
// want to stop tracking the open dialog even if it hasn't been closed, because the tracking
161
- // determines when `aria-hidden ` is removed from elements outside the dialog.
162
+ // determines when `inert ` is removed from elements outside the dialog.
162
163
reverseForEach ( this . _openDialogsAtThisLevel , dialog => {
163
164
// Check for `false` specifically since we want `undefined` to be interpreted as `true`.
164
165
if ( dialog . config . closeOnDestroy === false ) {
@@ -347,18 +348,29 @@ export class Dialog implements OnDestroy {
347
348
if ( index > - 1 ) {
348
349
( this . openDialogs as DialogRef < R , C > [ ] ) . splice ( index , 1 ) ;
349
350
350
- // If all the dialogs were closed, remove/restore the `aria-hidden`
351
+ // If all the dialogs were closed, remove/restore the inert attribute
351
352
// to a the siblings and emit to the `afterAllClosed` stream.
352
353
if ( ! this . openDialogs . length ) {
353
- this . _ariaHiddenElements . forEach ( ( previousValue , element ) => {
354
- if ( previousValue ) {
355
- element . setAttribute ( 'aria-hidden' , previousValue ) ;
354
+ this . _inertElements . forEach ( ( previousValue , element ) => {
355
+ const [ ariaHidden , inert ] = previousValue ;
356
+
357
+ // Note: this code is somewhat repetitive, but we want to use static strings inside
358
+ // the `setAttribute` calls so that we don't trip up some internal XSS checks.
359
+ if ( ariaHidden ) {
360
+ element . setAttribute ( 'aria-hidden' , ariaHidden ) ;
356
361
} else {
357
362
element . removeAttribute ( 'aria-hidden' ) ;
358
363
}
359
- } ) ;
360
364
361
- this . _ariaHiddenElements . clear ( ) ;
365
+ if ( _supportsInert ( ) ) {
366
+ if ( inert ) {
367
+ element . setAttribute ( 'inert' , inert ) ;
368
+ } else {
369
+ element . removeAttribute ( 'inert' ) ;
370
+ }
371
+ }
372
+ } ) ;
373
+ this . _inertElements . clear ( ) ;
362
374
363
375
if ( emitEvent ) {
364
376
this . _getAfterAllClosed ( ) . next ( ) ;
@@ -384,8 +396,17 @@ export class Dialog implements OnDestroy {
384
396
sibling . nodeName !== 'STYLE' &&
385
397
! sibling . hasAttribute ( 'aria-live' )
386
398
) {
387
- this . _ariaHiddenElements . set ( sibling , sibling . getAttribute ( 'aria-hidden' ) ) ;
399
+ const ariaHidden = sibling . getAttribute ( 'aria-hidden' ) ;
400
+ const inert = _supportsInert ( ) ? sibling . getAttribute ( 'inert' ) : null ;
401
+
402
+ // TODO(crisbeto): ideally we'd set only either `aria-hidden` or `inert` here, but
403
+ // at the moment of writing, some internal checks don't consider `inert` elements as
404
+ // removed from the a11y tree which reveals a bunch of pre-existing breakages.
405
+ this . _inertElements . set ( sibling , [ ariaHidden , inert ] ) ;
388
406
sibling . setAttribute ( 'aria-hidden' , 'true' ) ;
407
+ if ( _supportsInert ( ) ) {
408
+ sibling . setAttribute ( 'inert' , 'true' ) ;
409
+ }
389
410
}
390
411
}
391
412
}
0 commit comments