🎉 New features
- iOS:
onPositionChangenow reports a sheet's live position while it moves behind a dragging child sheet. (#744 by @lodev09) - The
autodetent now works with plugged scrollables — the sheet sizes to the scrollable's content height and resizes as content grows or shrinks. (#743 by @lodev09) - New
headerOptionsprop with apositionoption — set to'absolute'to float the header over the content (pinned to the top edge) and exclude it from theautodetent height. (#747 by @lodev09) - A relative footer now owns the bottom safe-area inset at the
autodetent — the inset is no longer added to the auto height, so the footer sits flush at the sheet's bottom edge. (#749 by @lodev09) - The footer now absorbs the bottom safe-area inset as padding when
insetAdjustmentisautomatic, regardless offooterOptions.position— content stays above the home indicator while the footer's background fills the inset, so no manual safe-area padding is needed. The inset is skipped while the keyboard is open. (#750 by @lodev09)
🐛 Bug fixes
- iOS: Smoother, more reliable
onPositionChange— drags emit at the touch rate, transitions track at the display's native refresh rate (120Hz on ProMotion), and a sheet behind a presenting child animates to its collapsed position instead of jumping or going stale.onWillDismissnow fires only when a drag-to-dismiss is committed on release, not prematurely mid-drag. (#756 by @lodev09) - iOS: A sheet stacked behind a child sheet no longer resizes its content in the background — UIKit's push-back scaling was reported as a size change, triggering spurious
onLayout. (#753 by @lodev09) - The keyboard-driven scroll inset now accounts for an absolute footer's height — focused inputs clear both the keyboard and the footer instead of hiding behind it. (#752 by @lodev09)
- A relative footer no longer floats above the keyboard — it stays in the layout flow behind it and keeps its safe-area inset. Only an absolute footer rises above the keyboard (
footerOptions.keyboardOffsetnow only applies there). (#754 by @lodev09) - Keyboard-driven sheet growth no longer corrupts
animatedIndex— iOS skips detent offset learning while the keyboard has the sheet grown and re-settles once it's away; Android clamps expected detent tops to the available height. Settle emits now learn at the final frame and bypass the dedupe, so presenting and settling land exactly on the detent index. (#761 by @lodev09)
💥 Breaking changes
- The footer now lays out relative by default — it takes up space below the content (still pinned to the bottom edge) and its height is included in the
autodetent calculation, but excluded from thepeekdetent (it's pushed off-screen at peek). Set the newfooterOptions.positionto'absolute'to restore the previous floating behavior. (#748 by @lodev09) - Content now lays out naturally like a regular view or a react-navigation screen — it wraps its children's height by default instead of filling the sheet. Pass
flex: 1viastyleto fill, and bound scrollables the same way (exceptautodetents, which stay auto-sized). (#746 by @lodev09) - Synchronous per-detent container layout — the container is sized to the sheet's visible height per detent and tracks it in realtime while dragging, on all platforms (previously sized to the screen height / largest detent). The
scrollableprop is removed — scrollables are auto-detected and work plugged in directly. Requires React Native 0.82+. (#735 by @lodev09)
💡 Others
Full Changelog: v3.11.10...v4.0.0-beta.1