Skip to content

Fixes an Android bug where a closed BottomSheet with a backdrop can block all touch events on the underlying screen after a cold start.#2706

Open
kanav22 wants to merge 1 commit into
gorhom:masterfrom
kanav22:fix/backdrop-touch-race-987c
Open

Fixes an Android bug where a closed BottomSheet with a backdrop can block all touch events on the underlying screen after a cold start.#2706
kanav22 wants to merge 1 commit into
gorhom:masterfrom
kanav22:fix/backdrop-touch-race-987c

Conversation

@kanav22

@kanav22 kanav22 commented Jun 29, 2026

Copy link
Copy Markdown

Fixes an Android bug where a closed BottomSheet with a backdrop can block all touch events on the underlying screen after a cold start.

Closes #2680

Problem
When a screen mounts a closed bottom sheet (index={-1}) with a BottomSheetBackdrop, some Android devices stop receiving scroll and button presses on the content behind the sheet. The UI renders correctly, but touches appear to be swallowed. Backgrounding the app and returning restores interaction without navigating away.

Reported on devices including Samsung (Android 14) and Xiaomi (Android 11).

Root cause
Two independent issues in BottomSheetBackdrop:

  1. Mount race condition
    pointerEvents was always initialized to 'auto' when enableTouchThrough is false. useAnimatedReaction can fire before the mount useEffect sets isMounted.current = true. Because handleContainerTouchability only updates state when mounted, that first update is silently skipped and the invisible backdrop keeps intercepting touches.

  2. Floating-point animatedIndex
    On some devices, animatedIndex settles at -0.999… instead of exactly -1. With disappearsOnIndex={-1}, the check animatedIndex.value <= disappearsOnIndex evaluates to false, so pointerEvents never switches to 'none'.

Solution
Derive the initial pointerEvents value from the current animatedIndex instead of defaulting to 'auto'
Sync pointerEvents on mount to recover from the race where the animated reaction fires before the component is mounted
Use an epsilon-based closed-state check (index <= disappearsOnIndex + 0.01) so near-closed values like -0.9999 are treated as closed without affecting partially open positions during animations
How to reproduce (before fix)
Use @gorhom/bottom-sheet@5.2.14
Render a screen with scrollable content and a closed bottom sheet (index={-1})
Add a backdrop with appearsOnIndex={0} and disappearsOnIndex={-1}
Cold start on an affected Android device
Try scrolling or pressing buttons behind the sheet
Observe that touches are blocked until the app is backgrounded and resumed
<BottomSheet
ref={sheetRef}
index={-1}
enableDynamicSizing
enablePanDownToClose
backdropComponent={renderBackdrop}

...

Test plan

yarn typescript
passes

biome check
passes on the changed file
Cold-start repro on physical Android device (Samsung / Xiaomi class devices)
Verify backdrop still captures presses when the sheet is open
Verify
enableTouchThrough
behavior is unchanged
Verify opening/closing the sheet still works as expected
Risks / notes
The epsilon value (0.01) is intentionally small so mid-animation indices (e.g. -0.3) are not incorrectly treated as closed
This is a targeted change to BottomSheetBackdrop.tsx only; no API changes
Related community workaround was setting disappearsOnIndex={-0.5} — this fix addresses the underlying comparison issue without requiring consumers to change their config

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: Invisible closed backdrop can block touches after cold start on some Android devices

1 participant