@@ -515,19 +515,7 @@ export const present = async <OverlayPresentOptions>(
515515 document . body . classList . add ( BACKDROP_NO_SCROLL ) ;
516516
517517 hideUnderlyingOverlaysFromScreenReaders ( overlay . el ) ;
518-
519- /**
520- * Set aria-hidden="true" to hide the overlay from screen readers
521- * during the animation. This ensures that assistive technologies
522- * like TalkBack do not announce or interact with the content until
523- * the animation is complete, avoiding confusion for users.
524- *
525- * Additionally, it prevents focus rings from appearing in incorrect
526- * positions due to the transition (specifically `transform` styles),
527- * ensuring that when aria-hidden is removed, the focus rings are
528- * correctly displayed in the final location of the elements.
529- */
530- overlay . el . setAttribute ( 'aria-hidden' , 'true' ) ;
518+ hideAnimatingOverlayFromScreenReaders ( overlay . el ) ;
531519
532520 overlay . presented = true ;
533521 overlay . willPresent . emit ( ) ;
@@ -573,6 +561,11 @@ export const present = async <OverlayPresentOptions>(
573561 * it would still have aria-hidden on being presented again.
574562 * Removing it here ensures the overlay is visible to screen
575563 * readers.
564+ *
565+ * If this overlay was being presented, then it was hidden
566+ * from screen readers during the animation. Now that the
567+ * animation is complete, we can reveal the overlay to
568+ * screen readers.
576569 */
577570 overlay . el . removeAttribute ( 'aria-hidden' ) ;
578571} ;
@@ -657,6 +650,13 @@ export const dismiss = async <OverlayDismissOptions>(
657650 overlay . presented = false ;
658651
659652 try {
653+ /**
654+ * There is no need to show the overlay to screen readers during
655+ * the dismiss animation. This is because the overlay will be removed
656+ * from the DOM after the animation is complete.
657+ */
658+ hideAnimatingOverlayFromScreenReaders ( overlay . el ) ;
659+
660660 // Overlay contents should not be clickable during dismiss
661661 overlay . el . style . setProperty ( 'pointer-events' , 'none' ) ;
662662 overlay . willDismiss . emit ( { data, role } ) ;
@@ -942,6 +942,25 @@ export const createTriggerController = () => {
942942 } ;
943943} ;
944944
945+ /**
946+ * The overlay that is being animated also needs to hide from screen
947+ * readers during its animation. This ensures that assistive technologies
948+ * like TalkBack do not announce or interact with the content until the
949+ * animation is complete, avoiding confusion for users.
950+ *
951+ * If the overlay is being presented, it prevents focus rings from appearing
952+ * in incorrect positions due to the transition (specifically `transform`
953+ * styles), ensuring that when aria-hidden is removed, the focus rings are
954+ * correctly displayed in the final location of the elements.
955+ *
956+ * @param overlay - The overlay that is being animated.
957+ */
958+ const hideAnimatingOverlayFromScreenReaders = ( overlay : HTMLIonOverlayElement ) => {
959+ if ( doc === undefined ) return ;
960+
961+ overlay . setAttribute ( 'aria-hidden' , 'true' ) ;
962+ } ;
963+
945964/**
946965 * Ensure that underlying overlays have aria-hidden if necessary so that screen readers
947966 * cannot move focus to these elements. Note that we cannot rely on focus/focusin/focusout
0 commit comments