React Native Bottom Sheet provides bottom-sheet components for React Native.
-
Install React Native Bottom Sheet:
npm i @swmansion/react-native-bottom-sheet
-
Ensure the peer dependencies are installed:
npm i react-native-gesture-handler@^2.14.0 react-native-reanimated@^3.16.0 react-native-safe-area-context@^4.0.0 react-native-worklets@^0.4.0
-
Wrap your app with
GestureHandlerRootViewandBottomSheetProvider:const App = () => ( <GestureHandlerRootView> <BottomSheetProvider>{/* ... */}</BottomSheetProvider> </GestureHandlerRootView> );
The library provides two components: BottomSheet (inline) and
ModalBottomSheet (modal). Both render their children as the sheet content
(including any background) and are controlled via detents, index,
and onIndexChange.
BottomSheet renders within your screen layout.
const [index, setIndex] = useState(0);
const insets = useSafeAreaInsets();<BottomSheet index={index} onIndexChange={setIndex}>
<View
style={{
backgroundColor: 'white',
padding: 16,
paddingBottom: insets.bottom + 16,
}}
>
<Text>Sheet content</Text>
</View>
</BottomSheet>ModalBottomSheet renders above other content with a scrim.
const [index, setIndex] = useState(0);
const insets = useSafeAreaInsets();<ModalBottomSheet index={index} onIndexChange={setIndex}>
<View
style={{
backgroundColor: 'white',
padding: 16,
paddingBottom: insets.bottom + 16,
}}
>
<Text>Sheet content</Text>
</View>
</ModalBottomSheet>Tapping the scrim collapses the sheet. You can provide a custom scrim via the
scrim prop, which receives a SharedValue that goes from 0 when collapsed to
1 when the first nonzero detent is reached:
<ModalBottomSheet
index={index}
onIndexChange={setIndex}
scrim={(progress) => (
<Animated.View
style={useAnimatedStyle(() => ({
backgroundColor: `rgba(0, 0, 255, ${0.3 * progress.value})`,
flex: 1,
}))}
/>
)}
>
{/* ... */}
</ModalBottomSheet>Detents are the points to which the sheet snaps. Each detent is either a number
(a fixed height in pixels) or 'max' (the sheet’s content height, capped by the
available screen height). The default detents are [0, 'max'].
The index prop is a zero-based index into the detents array.
onIndexChange is called when the sheet snaps to a different detent after
a drag. You can also control the sheet externally by updating the index
state.
const [index, setIndex] = useState(0);<BottomSheet // Or `ModalBottomSheet`.
detents={[0, 300, 'max']} // Collapsed, 300 px, content height.
index={index}
onIndexChange={setIndex}
>
{/* ... */}
</BottomSheet>If you want a detent to be reachable only via code (not by dragging), use the
object form or the programmatic helper. Programmatic detents are excluded from
drag snapping but can still be targeted via index updates.
<BottomSheet
detents={[0, programmatic(300), 'max']}
index={index}
onIndexChange={setIndex}
>
{/* ... */}
</BottomSheet>The position prop accepts a SharedValue that the library keeps in sync with
the sheet’s current position (the distance in pixels from the bottom of the
screen to the top of the sheet). Use it to drive animations tied to the
sheet position.
const position = useSharedValue(0);<BottomSheet // Or `ModalBottomSheet`.
index={index}
onIndexChange={setIndex}
position={position}
>
{/* ... */}
</BottomSheet>Use the openAnimationConfig and closeAnimationConfig props to tweak the
spring parameters for opening and closing.
For scrollable sheet content, use BottomSheetScrollView or
BottomSheetFlatList instead of the standard React Native components. These
integrate scrolling with the sheet’s drag gesture so that dragging down while
scrolled to the top collapses the sheet.
Both components expose imperative methods on their refs:
const scrollViewRef = useRef<BottomSheetScrollViewMethods>(null);
const listRef = useRef<BottomSheetFlatListMethods>(null);scrollViewRef.current?.scrollTo({ y: 0, animated: true });
listRef.current?.scrollToOffset({ offset: 0, animated: true });Founded in 2012, Software Mansion is a software agency with experience in building web and mobile apps. We are core React Native contributors and experts in dealing with all kinds of React Native issues. We can help you build your next dream product—hire us.
