Skip to content

iOS: parent stays untappable ~1–2s after animated dismiss (button/backdrop); pan-dismiss is fine #760

Description

@alperenkarip

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

  1. Present a bare TrueSheet over a screen full of tappable controls.
  2. Close via in-sheet buttonawait dismiss() (animated default).
  3. Immediately try to tap parent controls as soon as the sheet is visually gone / nearly gone.
  4. Repeat step 2–3 using tap on dimmed backdrop instead of the button.
  5. 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):

  • willToDidMs190–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

  1. Is animated backdrop/button dismiss expected to keep the presentation hit-test owner alive longer than pan interactive dismiss on iOS?
  2. Is there a recommended API/pattern so programmatic + outside-tap dismiss match pan for parent hit-testing?
  3. 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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions