@@ -38,6 +38,20 @@ let lastId = 0;
3838
3939export const activeAnimations = new WeakMap < OverlayInterface , Animation [ ] > ( ) ;
4040
41+ type OverlayWithFocusTrapProps = HTMLIonOverlayElement & {
42+ focusTrap ?: boolean ;
43+ showBackdrop ?: boolean ;
44+ backdropBreakpoint ?: number ;
45+ } ;
46+
47+ /**
48+ * Determines if the overlay's backdrop is always active (no background interaction).
49+ * Returns false if showBackdrop=false or backdropBreakpoint > 0.
50+ */
51+ const isBackdropAlwaysActive = ( el : OverlayWithFocusTrapProps ) : boolean => {
52+ return el . showBackdrop !== false && ! ( ( el . backdropBreakpoint ?? 0 ) > 0 ) ;
53+ } ;
54+
4155const createController = < Opts extends object , HTMLElm > ( tagName : string ) => {
4256 return {
4357 create ( options : Opts ) : Promise < HTMLElm > {
@@ -539,16 +553,9 @@ export const present = async <OverlayPresentOptions>(
539553 * view container subtree, skip adding aria-hidden/inert there
540554 * to avoid disabling the overlay.
541555 */
542- const overlayEl = overlay . el as HTMLIonOverlayElement & {
543- focusTrap ?: boolean ;
544- showBackdrop ?: boolean ;
545- backdropBreakpoint ?: number ;
546- } ;
556+ const overlayEl = overlay . el as OverlayWithFocusTrapProps ;
547557 const shouldTrapFocus = overlayEl . tagName !== 'ION-TOAST' && overlayEl . focusTrap !== false ;
548- // Only lock out root content when backdrop is always active. Developers relying on
549- // showBackdrop=false or backdropBreakpoint expect background interaction at some point.
550- const backdropAlwaysActive = overlayEl . showBackdrop !== false && ! ( ( overlayEl . backdropBreakpoint ?? 0 ) > 0 ) ;
551- const shouldLockRoot = shouldTrapFocus && backdropAlwaysActive ;
558+ const shouldLockRoot = shouldTrapFocus && isBackdropAlwaysActive ( overlayEl ) ;
552559
553560 overlay . presented = true ;
554561 overlay . willPresent . emit ( ) ;
@@ -685,21 +692,12 @@ export const dismiss = async <OverlayDismissOptions>(
685692 * is dismissed.
686693 */
687694 const overlaysLockingRoot = presentedOverlays . filter ( ( o ) => {
688- const el = o as HTMLIonOverlayElement & {
689- focusTrap ?: boolean ;
690- showBackdrop ?: boolean ;
691- backdropBreakpoint ?: number ;
692- } ;
693- const backdropAlwaysActive = el . showBackdrop !== false && ! ( ( el . backdropBreakpoint ?? 0 ) > 0 ) ;
694- return el . tagName !== 'ION-TOAST' && el . focusTrap !== false && backdropAlwaysActive ;
695+ const el = o as OverlayWithFocusTrapProps ;
696+ return el . tagName !== 'ION-TOAST' && el . focusTrap !== false && isBackdropAlwaysActive ( el ) ;
695697 } ) ;
696- const overlayEl = overlay . el as HTMLIonOverlayElement & {
697- focusTrap ?: boolean ;
698- showBackdrop ?: boolean ;
699- backdropBreakpoint ?: number ;
700- } ;
701- const backdropAlwaysActive = overlayEl . showBackdrop !== false && ! ( ( overlayEl . backdropBreakpoint ?? 0 ) > 0 ) ;
702- const locksRoot = overlayEl . tagName !== 'ION-TOAST' && overlayEl . focusTrap !== false && backdropAlwaysActive ;
698+ const overlayEl = overlay . el as OverlayWithFocusTrapProps ;
699+ const locksRoot =
700+ overlayEl . tagName !== 'ION-TOAST' && overlayEl . focusTrap !== false && isBackdropAlwaysActive ( overlayEl ) ;
703701
704702 /**
705703 * If this is the last visible overlay that is trapping focus
0 commit comments