๐ True Sheet 4.0 is here!
Version 4 rewrites the sheet's layout engine. The sheet now lays out synchronously per detent, so the container is sized to the sheet's visible height and tracks it in realtime while dragging. On top of that, 4.0 brings first-class Expo Router support, overlays above sheets, custom backgrounds, and more than 30 bug fixes.
๐ A New Layout Engine
In v3, the content was sized to the largest detent, and resizing lagged a frame behind the sheet. In v4, the content resizes in the same frame as the sheet, on every platform:
- Sized per detent โ The container matches the sheet's visible height at each detent
- Tracks the drag โ Flex layouts, like a bottom-pinned button, follow the sheet's edge frame by frame
- Natural layout โ Content wraps its children's height, like a regular view. Pass
flex: 1viastyleto fill the sheet
Requirements:
- React Native >= 0.82 (Expo SDK 55+)
- New Architecture enabled
โจ What's New
๐ auto Detent with Scrollables
The scrollable prop is replaced by scrollableRef. Pass a ref of your ScrollView or FlatList to wire nested scrolling, keyboard insets, and auto sizing. With an auto detent, the sheet sizes to the scroll content and resizes as it grows or shrinks:
const scrollableRef = useRef<ScrollView>(null)
<TrueSheet scrollableRef={scrollableRef} detents={['auto']}>
<ScrollView ref={scrollableRef}>{/* ... */}</ScrollView>
</TrueSheet>The scrollable's bottom inset is now applied natively: the safe-area inset while the content can scroll, plus the height of an absolute footer floating over it. No more manual paddingBottom.
See the Detents guide and Scrolling guide for more details.
๐ฆถ Relative Footers and Floating Headers
Footers now take up space below the content by default and absorb the bottom safe-area inset. Set footerOptions.position to 'absolute' to float the footer over the content, like in v3.
Headers get the same option: set headerOptions.position to 'absolute' to float the header over the content and exclude it from the auto detent.
<TrueSheet
header={<MyHeader />}
headerOptions={{ position: 'absolute' }}
footer={<MyFooter />}
footerOptions={{ position: 'absolute' }}
>
{/* content */}
</TrueSheet>See the Header guide and Footer guide for more details.
๐งญ First-Class Expo Router Support
The sheet navigator is now built on standard-navigation, so one implementation works with both React Navigation and Expo Router. Expo Router apps get a ready-to-use Sheet layout from the new /navigation/expo-router entry point:
// app/_layout.tsx
import { Sheet } from '@lodev09/react-native-true-sheet/navigation/expo-router'
export default function SheetLayout() {
return (
<Sheet>
<Sheet.Screen name="index" />
<Sheet.Screen name="details" options={{ detents: ['auto', 1] }} />
</Sheet>
)
}It requires Expo SDK 57+ and works on Router 58. See the Navigation guide for more details.
๐ Overlays Above Sheets
The new TrueSheetOverlay component renders its children in a native layer above every presented sheet. Use it for toasts and dialogs instead of the FullWindowOverlay / Modal workaround:
import { TrueSheetOverlay } from '@lodev09/react-native-true-sheet'
<TrueSheetOverlay>
{visible && <Dialog onClose={() => setVisible(false)} />}
</TrueSheetOverlay>See the Overlays guide for more details.
๐ผ๏ธ Custom Backgrounds
The new background and backgroundStyle props work on iOS, Android, and Web. Use backgroundStyle.backgroundColor for an exact color or a tint over glass or blur, and pass any element to background for a custom one. detentBackgrounds changes the background per detent, with native transitions on iOS 26.1+:
<TrueSheet
detents={['peek', 'auto', 1]}
detentBackgrounds={[null, { blur: 'system-material' }, '#18202b']}
/>See the Backgrounds guide for more details.
๐จ Dim Color and Opacity
Customize the dim behind the sheet with dimColor and dimOpacity:
<TrueSheet detents={['auto', 1]} dimColor="#1b0a3c" dimOpacity={0.3}>
{/* content */}
</TrueSheet>See the Dimming guide for more details.
๐ Confirm Dismissals
The new onDismissAttempt event fires when the user tries to dismiss a sheet with dismissible set to false. Confirm unsaved changes, then call dismiss():
<TrueSheet
ref={sheet}
dismissible={!hasUnsavedChanges}
onDismissAttempt={() => confirmDiscard(() => sheet.current?.dismiss())}
>
{/* form */}
</TrueSheet>See the Dismissing guide for more details.
๐ฑ Foldables
On iOS 27.1+ foldables, foldOptions rests the sheet on the hinge when the device is half-folded:
<TrueSheet
detents={['peek', 0.6, 1]}
foldOptions={{ hingeDetentIndex: 1, hingeBehavior: 'snap' }}
>
{/* content */}
</TrueSheet>See the Foldables guide for more details.
โ And More
- ๐
dismissThresholdโ Set it to'short'to dismiss on a short drag or fling on Android and Web, like Compose Material3's sheet - ๐ค
lazyโ Set it tofalseto mount the content before the sheet presents - โจ๏ธ
autoFocusโ An input withautoFocusnow raises the keyboard together with the sheet - ๐
footerOptions.avoidKeyboardโ Keep an absolute footer behind the keyboard - ๐
scrollableOptions.keyboardOffsetโ Adjust the scrollable's bottom inset while the keyboard is open - โ๏ธ
placementโ Replacesanchor. The new'automatic'default uses the native placement on iOS 27+ - ๐ Element inspector โ The dev menu inspector now works inside a presented sheet
- ๐ Deep linking โ A new Deep Linking guide for cold-start deep links to sheets
- ๐ Expo SDK 58 โ Supports React Native 0.88
๐ Bug Fixes
4.0 includes more than 30 fixes across iOS, Android, and Web, including keyboard handling, stacked sheets, iPad windowing, accessibility, and the sheet navigator. See the release notes for the full list.
๐ฅ Breaking Changes
Version 4 includes some breaking changes:
- React Native 0.82+ required โ The new layout engine relies on synchronous Fabric state updates
scrollableRefโ Replaces thescrollableprop- Natural content layout โ Pass
flex: 1viastyleto fill the sheet - Relative footers โ Set
footerOptions.positionto'absolute'to keep a floating footer - Native insets โ Remove manual safe-area padding from footers and scroll content
placementโ Replacesanchor, and'left'/'right'become'leading'/'trailing'- Backgrounds โ
blurOptionsis removed, and blur now takes precedence overbackgroundColoron iOS - Navigation โ The sheet navigator requires the
standard-navigationpeer dependency and@react-navigation/native7.3+
Check out the Migration Guide for the full list and step-by-step upgrade instructions.
๐ Get Started
yarn add @lodev09/react-native-true-sheet@^4.0.0Or with Expo:
npx expo install @lodev09/react-native-true-sheetv3 is still supported for React Native 0.81-0.86 (Expo SDK 54-57). Install @lodev09/react-native-true-sheet@^3 and see the v3 docs.
Running into issues? Check out the Troubleshooting guide for common fixes.
๐ Thank You!
A huge thanks to everyone who contributed to this release: @maxlapides, @SamuelBrucksch, @IjzerenHein, @1kuko3, @vilindberg, @simondaigre, @ronnymajani, @nickcernera, @hukpo, @cpruijsen, @billouboq, @MAVERlCK and @AndriiSerheniuk. And thanks to everyone who tested the betas, reported issues, and shared feedback.
Have feedback? Open an issue!
