Try Live
Add Docs
Rankings
Pricing
Enterprise
Docs
Install
Install
Docs
Pricing
Enterprise
More...
More...
Try Live
Rankings
Add Docs
React Native Bottom Sheet
https://github.com/gorhom/react-native-bottom-sheet
Admin
A performant and interactive bottom sheet component for React Native with fully configurable
...
Tokens:
23,177
Snippets:
90
Trust Score:
9.9
Update:
6 days ago
Context
Skills
Chat
Benchmark
82
Suggestions
Latest
Show doc for...
Code
Info
Show Results
Context Summary (auto-generated)
Raw
Copy
Link
# React Native Bottom Sheet React Native Bottom Sheet is a performant, interactive bottom sheet component for React Native applications with fully configurable options. Built on top of React Native Reanimated v3 and React Native Gesture Handler v2, it provides smooth gesture interactions, snapping animations, and seamless keyboard handling for both iOS and Android platforms. The library supports React Native Web, making it a cross-platform solution for implementing bottom sheet UIs. The library offers extensive customization through props, hooks, and component overrides. Key features include dynamic sizing that automatically calculates content height, support for scrollable content via pre-integrated FlatList, ScrollView, and SectionList components, modal presentation with stack behavior, pull-to-refresh support, and accessibility features. It is fully written in TypeScript and compatible with Expo, making it suitable for production applications requiring native-quality sheet interactions. ## Installation ```bash yarn add @gorhom/bottom-sheet@^5 react-native-reanimated react-native-gesture-handler ``` ## Basic Bottom Sheet Usage The BottomSheet component provides an interactive sheet that can be swiped and snapped to predefined positions. It supports dynamic content sizing and can contain any React Native content including scrollable views. ```tsx import React, { useCallback, useMemo, useRef } from 'react'; import { View, Text, StyleSheet } from 'react-native'; import { GestureHandlerRootView } from 'react-native-gesture-handler'; import BottomSheet, { BottomSheetView } from '@gorhom/bottom-sheet'; const App = () => { // ref const bottomSheetRef = useRef<BottomSheet>(null); // callbacks const handleSheetChanges = useCallback((index: number) => { console.log('handleSheetChanges', index); }, []); // renders return ( <GestureHandlerRootView style={styles.container}> <BottomSheet ref={bottomSheetRef} onChange={handleSheetChanges} > <BottomSheetView style={styles.contentContainer}> <Text>Awesome 🎉</Text> </BottomSheetView> </BottomSheet> </GestureHandlerRootView> ); }; const styles = StyleSheet.create({ container: { flex: 1, backgroundColor: 'grey', }, contentContainer: { flex: 1, padding: 36, alignItems: 'center', }, }); export default App; ``` ## Bottom Sheet with Snap Points Configure specific snap points (positions) where the sheet can rest. Snap points can be specified as pixel values or percentages, and the sheet will animate smoothly between them when dragged. ```tsx import React, { useCallback, useRef, useMemo } from "react"; import { StyleSheet, View, Text, Button } from "react-native"; import { GestureHandlerRootView } from 'react-native-gesture-handler'; import BottomSheet, { BottomSheetView } from "@gorhom/bottom-sheet"; const App = () => { const sheetRef = useRef<BottomSheet>(null); const snapPoints = useMemo(() => ["25%", "50%", "90%"], []); const handleSheetChange = useCallback((index) => { console.log("handleSheetChange", index); }, []); const handleSnapPress = useCallback((index) => { sheetRef.current?.snapToIndex(index); }, []); const handleClosePress = useCallback(() => { sheetRef.current?.close(); }, []); return ( <GestureHandlerRootView style={styles.container}> <Button title="Snap To 90%" onPress={() => handleSnapPress(2)} /> <Button title="Snap To 50%" onPress={() => handleSnapPress(1)} /> <Button title="Snap To 25%" onPress={() => handleSnapPress(0)} /> <Button title="Close" onPress={() => handleClosePress()} /> <BottomSheet ref={sheetRef} snapPoints={snapPoints} enableDynamicSizing={false} onChange={handleSheetChange} > <BottomSheetView style={styles.contentContainer}> <Text>Awesome 🔥</Text> </BottomSheetView> </BottomSheet> </GestureHandlerRootView> ); }; const styles = StyleSheet.create({ container: { flex: 1, paddingTop: 200, }, contentContainer: { flex: 1, padding: 36, alignItems: 'center', }, }); export default App; ``` ## Bottom Sheet Modal The BottomSheetModal component wraps the BottomSheet with modal presentation functionality, including stack behavior for multiple modals. It requires a BottomSheetModalProvider wrapper and uses present/dismiss methods instead of being always visible. ```tsx import React, { useCallback, useMemo, useRef } from 'react'; import { View, Text, StyleSheet, Button } from 'react-native'; import { GestureHandlerRootView } from 'react-native-gesture-handler'; import { BottomSheetModal, BottomSheetView, BottomSheetModalProvider, } from '@gorhom/bottom-sheet'; const App = () => { const bottomSheetModalRef = useRef<BottomSheetModal>(null); const handlePresentModalPress = useCallback(() => { bottomSheetModalRef.current?.present(); }, []); const handleSheetChanges = useCallback((index: number) => { console.log('handleSheetChanges', index); }, []); return ( <GestureHandlerRootView style={styles.container}> <BottomSheetModalProvider> <Button onPress={handlePresentModalPress} title="Present Modal" color="black" /> <BottomSheetModal ref={bottomSheetModalRef} onChange={handleSheetChanges} > <BottomSheetView style={styles.contentContainer}> <Text>Awesome 🎉</Text> </BottomSheetView> </BottomSheetModal> </BottomSheetModalProvider> </GestureHandlerRootView> ); }; const styles = StyleSheet.create({ container: { flex: 1, padding: 24, justifyContent: 'center', backgroundColor: 'grey', }, contentContainer: { flex: 1, alignItems: 'center', }, }); export default App; ``` ## BottomSheetFlatList for Scrollable Content A pre-integrated FlatList component that works seamlessly with the bottom sheet gestures. It allows smooth scrolling within the sheet while maintaining swipe-to-dismiss and snap-to-position functionality. ```tsx import React, { useCallback, useRef, useMemo } from "react"; import { StyleSheet, View, Text, Button } from "react-native"; import { GestureHandlerRootView } from 'react-native-gesture-handler'; import BottomSheet, { BottomSheetFlatList } from "@gorhom/bottom-sheet"; const App = () => { const sheetRef = useRef<BottomSheet>(null); const data = useMemo( () => Array(50) .fill(0) .map((_, index) => `index-${index}`), [] ); const snapPoints = useMemo(() => ["25%", "50%", "90%"], []); const handleSheetChange = useCallback((index) => { console.log("handleSheetChange", index); }, []); const handleSnapPress = useCallback((index) => { sheetRef.current?.snapToIndex(index); }, []); const handleClosePress = useCallback(() => { sheetRef.current?.close(); }, []); const renderItem = useCallback( ({ item }) => ( <View style={styles.itemContainer}> <Text>{item}</Text> </View> ), [] ); return ( <GestureHandlerRootView style={styles.container}> <Button title="Snap To 90%" onPress={() => handleSnapPress(2)} /> <Button title="Snap To 50%" onPress={() => handleSnapPress(1)} /> <Button title="Snap To 25%" onPress={() => handleSnapPress(0)} /> <Button title="Close" onPress={() => handleClosePress()} /> <BottomSheet ref={sheetRef} snapPoints={snapPoints} enableDynamicSizing={false} onChange={handleSheetChange} > <BottomSheetFlatList data={data} keyExtractor={(i) => i} renderItem={renderItem} contentContainerStyle={styles.contentContainer} /> </BottomSheet> </GestureHandlerRootView> ); }; const styles = StyleSheet.create({ container: { flex: 1, paddingTop: 200, }, contentContainer: { backgroundColor: "white", }, itemContainer: { padding: 6, margin: 6, backgroundColor: "#eee", }, }); export default App; ``` ## BottomSheetScrollView for Custom Scrollable Content A pre-integrated ScrollView component that provides smooth scrolling interactions within the bottom sheet while maintaining gesture coordination. ```tsx import React, { useCallback, useRef, useMemo } from "react"; import { StyleSheet, View, Text, Button } from "react-native"; import { GestureHandlerRootView } from 'react-native-gesture-handler'; import BottomSheet, { BottomSheetScrollView } from "@gorhom/bottom-sheet"; const App = () => { const sheetRef = useRef<BottomSheet>(null); const data = useMemo( () => Array(50) .fill(0) .map((_, index) => `index-${index}`), [] ); const snapPoints = useMemo(() => ["25%", "50%", "90%"], []); const handleSheetChange = useCallback((index) => { console.log("handleSheetChange", index); }, []); const renderItem = useCallback( (item) => ( <View key={item} style={styles.itemContainer}> <Text>{item}</Text> </View> ), [] ); return ( <GestureHandlerRootView style={styles.container}> <BottomSheet ref={sheetRef} index={1} snapPoints={snapPoints} enableDynamicSizing={false} onChange={handleSheetChange} > <BottomSheetScrollView contentContainerStyle={styles.contentContainer}> {data.map(renderItem)} </BottomSheetScrollView> </BottomSheet> </GestureHandlerRootView> ); }; const styles = StyleSheet.create({ container: { flex: 1, paddingTop: 200, }, contentContainer: { backgroundColor: "white", }, itemContainer: { padding: 6, margin: 6, backgroundColor: "#eee", }, }); export default App; ``` ## BottomSheetBackdrop Component A pre-built backdrop component that dims the background when the sheet is open. It supports customizable opacity, press behavior (close, collapse, or snap to specific index), and animated appearance/disappearance based on snap point indices. ```tsx import React, { useCallback, useMemo, useRef } from "react"; import { View, Text, StyleSheet } from "react-native"; import { GestureHandlerRootView } from 'react-native-gesture-handler'; import BottomSheet, { BottomSheetView, BottomSheetBackdrop } from "@gorhom/bottom-sheet"; const App = () => { const bottomSheetRef = useRef<BottomSheet>(null); const snapPoints = useMemo(() => ["25%", "50%", "75%"], []); const handleSheetChanges = useCallback((index: number) => { console.log("handleSheetChanges", index); }, []); const renderBackdrop = useCallback( (props) => ( <BottomSheetBackdrop {...props} disappearsOnIndex={1} appearsOnIndex={2} /> ), [] ); return ( <GestureHandlerRootView style={styles.container}> <BottomSheet ref={bottomSheetRef} index={1} snapPoints={snapPoints} backdropComponent={renderBackdrop} enableDynamicSizing={false} onChange={handleSheetChanges} > <BottomSheetView style={styles.contentContainer}> <Text>Awesome 🎉</Text> </BottomSheetView> </BottomSheet> </GestureHandlerRootView> ); }; const styles = StyleSheet.create({ container: { flex: 1, padding: 24, backgroundColor: "grey", }, contentContainer: { flex: 1, alignItems: "center", }, }); export default App; ``` ## Custom Backdrop Component Create a custom backdrop with animated styles based on the sheet position. The backdrop receives animatedIndex and animatedPosition props that can be used with Reanimated to create custom animations. ```tsx import React, { useMemo } from "react"; import { BottomSheetBackdropProps } from "@gorhom/bottom-sheet"; import Animated, { Extrapolate, interpolate, useAnimatedStyle, } from "react-native-reanimated"; const CustomBackdrop = ({ animatedIndex, style }: BottomSheetBackdropProps) => { const containerAnimatedStyle = useAnimatedStyle(() => ({ opacity: interpolate( animatedIndex.value, [0, 1], [0, 1], Extrapolate.CLAMP ), })); const containerStyle = useMemo( () => [ style, { backgroundColor: "#a8b5eb", }, containerAnimatedStyle, ], [style, containerAnimatedStyle] ); return <Animated.View style={containerStyle} />; }; export default CustomBackdrop; ``` ## Custom Background Component Override the default sheet background with an animated component that responds to the sheet position. Useful for creating gradient backgrounds or color transitions based on sheet state. ```tsx import React, { useMemo } from "react"; import { BottomSheetBackgroundProps } from "@gorhom/bottom-sheet"; import Animated, { useAnimatedStyle, interpolateColor, } from "react-native-reanimated"; const CustomBackground: React.FC<BottomSheetBackgroundProps> = ({ style, animatedIndex, }) => { const containerAnimatedStyle = useAnimatedStyle(() => ({ backgroundColor: interpolateColor( animatedIndex.value, [0, 1], ["#ffffff", "#a8b5eb"] ), })); const containerStyle = useMemo( () => [style, containerAnimatedStyle], [style, containerAnimatedStyle] ); return <Animated.View pointerEvents="none" style={containerStyle} />; }; export default CustomBackground; ``` ## BottomSheetFooter Component A sticky footer component that remains at the bottom of the sheet regardless of scroll position. Useful for action buttons, navigation, or persistent controls within the sheet. ```tsx import React, { useCallback, useMemo, useRef } from 'react'; import { View, Text, StyleSheet } from 'react-native'; import { GestureHandlerRootView } from 'react-native-gesture-handler'; import BottomSheet, { BottomSheetFooter } from '@gorhom/bottom-sheet'; const App = () => { const bottomSheetRef = useRef<BottomSheet>(null); const snapPoints = useMemo(() => ['25%', '50%'], []); const renderFooter = useCallback( props => ( <BottomSheetFooter {...props} bottomInset={24}> <View style={styles.footerContainer}> <Text style={styles.footerText}>Footer</Text> </View> </BottomSheetFooter> ), [] ); return ( <GestureHandlerRootView style={styles.container}> <BottomSheet ref={bottomSheetRef} index={1} snapPoints={snapPoints} footerComponent={renderFooter} > <View style={styles.contentContainer}> <Text>Awesome 🎉</Text> </View> </BottomSheet> </GestureHandlerRootView> ); }; const styles = StyleSheet.create({ container: { flex: 1, padding: 24, backgroundColor: 'grey', }, contentContainer: { flex: 1, alignItems: 'center', }, footerContainer: { padding: 12, margin: 12, borderRadius: 12, backgroundColor: '#80f', }, footerText: { textAlign: 'center', color: 'white', fontWeight: '800', }, }); export default App; ``` ## Keyboard Handling with BottomSheetTextInput Handle keyboard appearance with the pre-integrated TextInput component. The sheet automatically adjusts position when the keyboard appears, with configurable behavior options. ```tsx import React, { useMemo } from "react"; import { View, StyleSheet } from "react-native"; import BottomSheet, { BottomSheetTextInput } from "@gorhom/bottom-sheet"; const App = () => { const snapPoints = useMemo(() => ["25%"], []); return ( <View style={styles.container}> <BottomSheet snapPoints={snapPoints}> <View style={styles.contentContainer}> <BottomSheetTextInput value="Awesome 🎉" style={styles.textInput} /> </View> </BottomSheet> </View> ); }; const styles = StyleSheet.create({ container: { flex: 1, padding: 24, backgroundColor: "grey", }, textInput: { alignSelf: "stretch", marginHorizontal: 12, marginBottom: 12, padding: 12, borderRadius: 12, backgroundColor: "grey", color: "white", textAlign: "center", }, contentContainer: { flex: 1, alignItems: "center", }, }); export default App; ``` ## useBottomSheet Hook Access bottom sheet methods and animated values from any component within the sheet. Provides expand, collapse, close, snapToIndex, snapToPosition methods, plus animatedIndex and animatedPosition values. ```tsx import React from 'react'; import { View, Button } from 'react-native'; import { useBottomSheet } from '@gorhom/bottom-sheet'; const SheetContent = () => { const { expand, collapse, close, snapToIndex, animatedIndex, animatedPosition } = useBottomSheet(); return ( <View> <Button title="Expand" onPress={expand} /> <Button title="Collapse" onPress={collapse} /> <Button title="Close" onPress={close} /> <Button title="Snap to 50%" onPress={() => snapToIndex(1)} /> </View> ); }; ``` ## useBottomSheetModal Hook Access modal-specific methods from components within BottomSheetModalProvider. Allows dismissing modals by key or dismissing all open modals at once. ```tsx import React from 'react'; import { View, Button } from 'react-native'; import { useBottomSheetModal } from '@gorhom/bottom-sheet'; const SheetContent = () => { const { dismiss, dismissAll } = useBottomSheetModal(); return ( <View> <Button title="Dismiss Current" onPress={dismiss} /> <Button title="Dismiss All" onPress={dismissAll} /> </View> ); }; ``` ## useBottomSheetSpringConfigs Hook Generate spring animation configurations for custom sheet animations. Allows fine-tuning of animation behavior with damping, stiffness, and other spring physics parameters. ```tsx import React from 'react'; import BottomSheet, { useBottomSheetSpringConfigs } from '@gorhom/bottom-sheet'; const SheetContent = () => { const animationConfigs = useBottomSheetSpringConfigs({ damping: 80, overshootClamping: true, restDisplacementThreshold: 0.1, restSpeedThreshold: 0.1, stiffness: 500, }); return ( <BottomSheet animationConfigs={animationConfigs}> {/* Content */} </BottomSheet> ); }; ``` ## useBottomSheetTimingConfigs Hook Generate timing-based animation configurations for predictable, duration-controlled animations. Supports custom easing functions from Reanimated. ```tsx import React from 'react'; import BottomSheet, { useBottomSheetTimingConfigs } from '@gorhom/bottom-sheet'; import { Easing } from 'react-native-reanimated'; const SheetContent = () => { const animationConfigs = useBottomSheetTimingConfigs({ duration: 250, easing: Easing.exp, }); return ( <BottomSheet animationConfigs={animationConfigs}> {/* Content */} </BottomSheet> ); }; ``` ## useBottomSheetScrollableCreator Hook Create custom scrollable components for third-party virtualized lists like LegendList or FlashList. Returns a scroll component that integrates properly with the bottom sheet's gesture handling. ```tsx import React from 'react'; import BottomSheet, { useBottomSheetScrollableCreator } from '@gorhom/bottom-sheet'; import { LegendList } from '@legendapp/list'; const SheetContent = () => { const BottomSheetLegendListScrollable = useBottomSheetScrollableCreator(); return ( <BottomSheet> <LegendList data={data} renderItem={renderItem} renderScrollComponent={BottomSheetLegendListScrollable} /> </BottomSheet> ); }; ``` ## Methods Reference The BottomSheet component exposes several imperative methods accessible via ref: `snapToIndex(index, animationConfigs?)` snaps to a specific snap point index, `snapToPosition(position, animationConfigs?)` snaps to an arbitrary pixel position, `expand(animationConfigs?)` snaps to the maximum snap point, `collapse(animationConfigs?)` snaps to the minimum snap point, `close(animationConfigs?)` closes the sheet, and `forceClose(animationConfigs?)` closes without allowing interruption. ```tsx import React, { useRef } from 'react'; import { Button } from 'react-native'; import BottomSheet from '@gorhom/bottom-sheet'; const App = () => { const bottomSheetRef = useRef<BottomSheet>(null); const handleClosePress = () => bottomSheetRef.current?.close(); const handleExpandPress = () => bottomSheetRef.current?.expand(); const handleCollapsePress = () => bottomSheetRef.current?.collapse(); const handleSnapTo50 = () => bottomSheetRef.current?.snapToPosition('50%'); const handleSnapToIndex = () => bottomSheetRef.current?.snapToIndex(1); return ( <> <Button title="Close" onPress={handleClosePress} /> <Button title="Expand" onPress={handleExpandPress} /> <Button title="Collapse" onPress={handleCollapsePress} /> <Button title="Snap to 50%" onPress={handleSnapTo50} /> <Button title="Snap to Index 1" onPress={handleSnapToIndex} /> <BottomSheet ref={bottomSheetRef}> {/* Content */} </BottomSheet> </> ); }; ``` ## Summary React Native Bottom Sheet is the go-to solution for implementing bottom sheet interactions in React Native applications. Its primary use cases include action sheets for user choices, modal forms with keyboard handling, settings panels, content drawers, and map-style overlays like Apple Maps. The library excels at scenarios requiring smooth gesture-based interactions, multiple snap positions, and scrollable content within sheets. Integration follows a straightforward pattern: wrap your app with GestureHandlerRootView, use the BottomSheet component with children wrapped in BottomSheetView (for static content) or BottomSheetFlatList/BottomSheetScrollView (for scrollable content). For modal use cases, add BottomSheetModalProvider and use BottomSheetModal with present/dismiss methods. The library's hook-based API (useBottomSheet, useBottomSheetModal) enables deep integration with component trees, while animation configuration hooks allow precise control over motion design. Custom components for backdrop, background, handle, and footer provide complete visual customization while maintaining the core interaction functionality.