Skip to content

fix: footer touch swallowing and safe area inset bugs#589

Open
isaacrowntree wants to merge 1 commit intolodev09:mainfrom
isaacrowntree:fix/footer-touch-and-safe-area
Open

fix: footer touch swallowing and safe area inset bugs#589
isaacrowntree wants to merge 1 commit intolodev09:mainfrom
isaacrowntree:fix/footer-touch-and-safe-area

Conversation

@isaacrowntree
Copy link
Contributor

Summary

  • iOS: Footer buttons/touchables don't respond to taps because Fabric's touch system hit-tests using stale Yoga frames while AutoLayout has moved the footer to a different position. Fix: give the footer its own RCTSurfaceTouchHandler so it has an independent coordinate space rooted at its actual frame.
  • Android: Footer touches dispatched to JS twice — once by dispatchTouchEvent routing to footer's RootView, and again by onInterceptTouchEvent/onTouchEvent on the ViewController. Fix: skip JS dispatch in the ViewController when the touch is in footer bounds.
  • iOS: Footer ignores safe area insets — content renders behind the home indicator on notched iPhones. Fix: pin to safeAreaLayoutGuide.bottomAnchor instead of bottomAnchor.
  • Android: Footer renders behind the navigation/gesture bar. Fix: subtract bottomInset in positionFooter (skipped when keyboard is visible since currentKeyboardInset already accounts for it).

Root cause (iOS touch bug)

TrueSheetFooterView.updateLayoutMetrics skips [super updateLayoutMetrics:...] after initial layout (line 93-96), so the Yoga frame goes stale while AutoLayout moves the view to the container bottom. RCTSurfaceTouchHandler on the container hit-tests using Yoga frames → can't find the footer at its visual position → touches dropped or delivered to the wrong component.

The fix mirrors the existing Android pattern where TrueSheetFooterView implements RootView with its own JSTouchDispatcher — on iOS we achieve the same by giving the footer its own RCTSurfaceTouchHandler.

Test plan

  • Tap Button and TouchableOpacity in footer on physical iOS device — taps register
  • Tap footer buttons on physical Android device — taps register, no double-press
  • Footer content doesn't render behind home indicator (notched iPhone)
  • Footer content doesn't render behind gesture bar (Android)
  • Keyboard avoidance still works — footer moves up with keyboard
  • Test with dismissible={false}
  • Test at different detent sizes (small, medium, full)
  • Test with and without insetAdjustment="automatic"

Reproduction app: https://github.com/isaacrowntree/truesheet-touch-repro

🤖 Generated with Claude Code

@vercel
Copy link

vercel bot commented Mar 4, 2026

@isaacrowntree is attempting to deploy a commit to the Jovanni's projects Team on Vercel.

A member of the Team first needs to authorize it.

@lodev09
Copy link
Owner

lodev09 commented Mar 4, 2026

Thanks @isaacrowntree!

Do you have a repro from a fork of this repo that I can replicate on my end prior to your changes? I want to test this properly.

isaacrowntree added a commit to isaacrowntree/truesheet-touch-repro that referenced this pull request Mar 10, 2026
Reproduces two FooterComponent bugs:
1. Footer touches dropped on iOS, doubled on Android
2. Footer renders behind safe area insets on both platforms

Includes tap log to detect double-fire on Android and a
control button inside the sheet body for comparison.

Related: lodev09/react-native-true-sheet#589

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
iOS: Give footer its own RCTSurfaceTouchHandler so touches are hit-tested
against the footer's actual AutoLayout frame instead of the stale Yoga
frame in the container's touch handler. Pin footer bottom constraint to
safeAreaLayoutGuide.bottomAnchor so content doesn't render behind the
home indicator on notched devices.

Android: Skip JS touch dispatch in ViewController's onInterceptTouchEvent
and onTouchEvent when the touch lands in footer bounds, preventing double
dispatch (footer's own RootView handles it). Subtract bottomInset in
positionFooter so footer content doesn't render behind the gesture bar.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@isaacrowntree isaacrowntree force-pushed the fix/footer-touch-and-safe-area branch from d8f9c97 to 36e4804 Compare March 10, 2026 00:41
isaacrowntree added a commit to isaacrowntree/react-native-true-sheet that referenced this pull request Mar 10, 2026
Makes BasicSheet's footer tappable with an Alert so the touch
swallowing bug is immediately visible on physical devices.

iOS: taps on the footer are silently dropped
Android: taps fire twice (double alert)

Related: lodev09#589

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@isaacrowntree
Copy link
Contributor Author

isaacrowntree commented Mar 10, 2026

Hey @lodev09! Here's a repro branch on my fork of this repo:

isaacrowntree/react-native-true-sheet@repro/footer-touch

It adds a FooterReproSheet to the Test Screen in the example app with three variants covering all the test cases:

Button What it tests
Footer Repro Tappable button + TextInput in footer (touch bug + keyboard avoidance)
Footer (dismissible=false) Same footer with dismissible={false}
Footer (insetAdjustment=auto) Same footer with insetAdjustment="automatic"

All three use detents={['auto', 'medium', 'large']} so you can test at different sizes.

On a physical device before the fix:

  • iOS: footer button taps are silently dropped, TextInput can't be focused
  • Android: footer button taps fire twice (double alert)
  • Both: footer renders behind home indicator / gesture bar on notched devices

The existing BasicSheet footer is also made tappable for a quick sanity check.

I also rebased this PR on latest main so the conflicts are resolved.

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.

2 participants