Summary
On physical iOS, after an animated sheet dismiss, the presenting screen does not receive taps for roughly 1–2 seconds.
This happens for:
- programmatic close (
await sheet.current?.dismiss() / in-sheet close button calling dismiss())
- tap outside (dimmed backdrop dismiss)
It does not happen (or is much shorter / feels normal) for:
- pan-down interactive dismiss
So the split appears to be interactive pan dismiss vs animated non-pan dismiss (button + backdrop), not “FITOS shell” specific — we can reproduce on a bare TrueSheet with docs-style usage.
Environment
@lodev09/react-native-true-sheet: 3.11.9 (clean npm, no package patch)
react-native: 0.83.6
- Expo SDK: 55
- New Architecture / Fabric: enabled
- Platform: iOS physical device (also observed in our app workflow; simulator not treated as source of truth here)
- Presentation: standard
TrueSheet (not TrueSheet Navigator)
Minimal usage shape (docs-aligned)
const sheet = useRef<TrueSheet>(null)
// open
await sheet.current?.present()
// close (button)
await sheet.current?.dismiss() // default animated: true
return (
<TrueSheet
ref={sheet}
detents={['auto', 1]}
header={/* title + close that calls dismiss() */}
footer={/* actions */}
onDidDismiss={() => {
// parent clears controlled visible / form reset
}}
>
<View>{/* short form fields */}</View>
</TrueSheet>
)
Notes:
- No
scrollable (short form; docs: auto + scrollable unsupported together).
- Defaults for
grabber / dimmed / dismissible / draggable.
- Parent may bridge a controlled
visible flag to present() / dismiss(); the dead zone also appears when closing via backdrop tap (no JS button).
Steps to reproduce
- Present a bare
TrueSheet over a screen full of tappable controls.
- Close via in-sheet button →
await dismiss() (animated default).
- Immediately try to tap parent controls as soon as the sheet is visually gone / nearly gone.
- Repeat step 2–3 using tap on dimmed backdrop instead of the button.
- Compare with pan-down dismiss, then immediately tap parent.
Expected
Parent becomes tappable as soon as the sheet finishes dismissing (or during late pan, consistent with interactive dismiss). Button and backdrop dismiss should not leave a multi-second dead zone.
Actual
| Dismiss path |
Parent tappable |
| Pan-down |
OK (can interact during/soon after gesture) |
Close button → dismiss() |
Blocked ~1–2s after close |
| Backdrop outside tap |
Same ~1–2s block |
Device-side timing samples (app instrumentation)
JS-thread timestamps around dismiss (illustrative samples from our probe):
Button path (bad / variable):
willToDidMs ≈ 190–510 (native settle can be short when non-animated; longer when animated)
deadZoneMs (willDismiss → first parent touch) often ~1000–1700+, sometimes lower (~300) if the user taps later/earlier
- Post-
didDismiss gap can still be hundreds of ms to >1s before first parent touch registers
Pan path (OK):
- First parent touch often before
didDismiss
deadZoneMs from willDismiss typically ~230–340
We also intermittently see Fabric logs under stress, e.g. events dropped with instanceHandle is null (not always correlated 1:1, but appears around dismiss churn).
What we already ruled out
- Not our AppBottomSheet shell: reproduced on bare TrueSheet.
- Not only the X control: backdrop dismiss hits the same class of failure.
#547 / #548 (isModalInPresentation / touch passthrough while sheet is open with dismissible={false} + dimmed={false}): already present in 3.11.9; different symptom (open-sheet passthrough vs post-dismiss dead zone). Our repro uses default dismissible/dimmed.
- Docs troubleshooting has no entry for post-dismiss parent untouchable.
- Version hopping within 3.11.x has no changelog entry that clearly targets this.
Workarounds we observed (not product-complete)
dismiss(false) reduces the pain (faster teardown) but removes close animation.
- Interactive pan dismiss remains the healthy path.
- Custom “collapse detent then
dismiss(false)” hacks caused stuck/inconsistent motion and are not a good product fix.
Ask
- Is animated backdrop/button dismiss expected to keep the presentation hit-test owner alive longer than pan interactive dismiss on iOS?
- Is there a recommended API/pattern so programmatic + outside-tap dismiss match pan for parent hit-testing?
- Happy to add a minimal public repro repo/Snack if that helps — we can strip this to example-app style.
Related (not duplicates)
Thanks — this is blocking “close sheet → immediately tap parent” UX for any non-pan dismiss path.
Summary
On physical iOS, after an animated sheet dismiss, the presenting screen does not receive taps for roughly 1–2 seconds.
This happens for:
await sheet.current?.dismiss()/ in-sheet close button callingdismiss())It does not happen (or is much shorter / feels normal) for:
So the split appears to be interactive pan dismiss vs animated non-pan dismiss (button + backdrop), not “FITOS shell” specific — we can reproduce on a bare
TrueSheetwith docs-style usage.Environment
@lodev09/react-native-true-sheet: 3.11.9 (clean npm, no package patch)react-native: 0.83.6TrueSheet(not TrueSheet Navigator)Minimal usage shape (docs-aligned)
Notes:
scrollable(short form; docs:auto+scrollableunsupported together).grabber/dimmed/dismissible/draggable.visibleflag topresent()/dismiss(); the dead zone also appears when closing via backdrop tap (no JS button).Steps to reproduce
TrueSheetover a screen full of tappable controls.await dismiss()(animated default).Expected
Parent becomes tappable as soon as the sheet finishes dismissing (or during late pan, consistent with interactive dismiss). Button and backdrop dismiss should not leave a multi-second dead zone.
Actual
dismiss()Device-side timing samples (app instrumentation)
JS-thread timestamps around dismiss (illustrative samples from our probe):
Button path (bad / variable):
willToDidMs≈ 190–510 (native settle can be short when non-animated; longer when animated)deadZoneMs(willDismiss → first parent touch) often ~1000–1700+, sometimes lower (~300) if the user taps later/earlierdidDismissgap can still be hundreds of ms to >1s before first parent touch registersPan path (OK):
didDismissdeadZoneMsfrom willDismiss typically ~230–340We also intermittently see Fabric logs under stress, e.g. events dropped with
instanceHandle is null(not always correlated 1:1, but appears around dismiss churn).What we already ruled out
#547/#548(isModalInPresentation/ touch passthrough while sheet is open withdismissible={false}+dimmed={false}): already present in 3.11.9; different symptom (open-sheet passthrough vs post-dismiss dead zone). Our repro uses defaultdismissible/dimmed.Workarounds we observed (not product-complete)
dismiss(false)reduces the pain (faster teardown) but removes close animation.dismiss(false)” hacks caused stuck/inconsistent motion and are not a good product fix.Ask
Related (not duplicates)
dismissible={false})<Modal>visible={false}(blank screen) — related “dismiss-first” guidance, different failure modeThanks — this is blocking “close sheet → immediately tap parent” UX for any non-pan dismiss path.