A customizable React Native bottom sheet component with gesture support, keyboard awareness, and smooth animations.
npm install szn-ui-react-native-bottom-sheetbash
npm install szn-ui-react-native-bottom-sheet
`
$3
This package requires the following peer dependencies:
`bash
npm install react-native-gesture-handler react-native-reanimated
`
Make sure to follow the installation instructions for:
- react-native-gesture-handler
- react-native-reanimated
Usage
`tsx
import React, { useState } from 'react';
import { View, Text, Button } from 'react-native';
import { BottomSheet } from "szn-ui-react-native-bottom-sheet";
const App = (): JSX.Element => {
const [isVisible, setIsVisible] = useState(false);
return (
);
};
export default App;
`
Props
| Prop | Type | Default | Description |
| ----------------- | ------------ | --------------------- | ------------------------------------------------------------------------ |
| isVisible | boolean | Required | Controls the visibility of the bottom sheet |
| onClose | () => void | Required | Callback when the sheet should be closed |
| children | ReactNode | Required | Content to render inside the bottom sheet |
| height | number | SCREEN_HEIGHT * 0.9 | Height of the bottom sheet |
| backgroundColor | string | 'white' | Background color of the bottom sheet |
| showDragHandle | boolean | true | Whether to show the drag handle |
| containerStyle | ViewStyle | undefined | Additional styles for the sheet container |
| title | string | undefined | Title text to display in the header |
| showHeader | boolean | false | Whether to show the header with title and cancel button |
| cancelText | string | 'Cancel' | Text for the cancel button in header |
You can customize the sheet's background using either the backgroundColor prop or via containerStyle, but if both are provided, the backgroundColor prop takes precedence.
Examples
$3
`tsx
isVisible={isVisible}
onClose={() => setIsVisible(false)}
showHeader
title="Settings"
cancelText="Done"
>
Settings content here
`
$3
`tsx
import React, { useRef, useState } from 'react';
import { View, Text, TouchableOpacity } from 'react-native';
import { BottomSheet, BottomSheetRef } from 'szn-ui-react-native-bottom-sheet';
import { Ionicons } from '@expo/vector-icons';
export default function MyScreen(): JSX.Element {
const [isVisible, setIsVisible] = useState(false);
const sheetRef = useRef(null);
const handleOpen = () => setIsVisible(true);
const handleClose = () => setIsVisible(false);
return (
<>
Open Bottom Sheet
ref={sheetRef}
isVisible={isVisible}
onClose={handleClose}
showHeader={false}
showDragHandle={true}
height={600}
>
My Custom Header
onPress={() => sheetRef.current?.dismiss()}
className="p-2 bg-gray-100 rounded-full"
>
Sheet Content Here...
>
);
}
`
$3
`tsx
isVisible={isVisible}
onClose={() => setIsVisible(false)}
height={400}
>
Custom height content
`
$3
`tsx
const [step, setStep] = useState(1);
return (
isVisible={true}
onClose={() => {}}
height={step === 1 ? 200 : step === 2 ? 400 : 600}
>
{step === 1 && setStep(2)} />}
{step === 2 && setStep(3)} />}
{step === 3 && }
);
`
$3
`tsx
isVisible={isVisible}
onClose={() => setIsVisible(false)}
backgroundColor="#fef2f2"
>
Light pink background
`
$3
`tsx
isVisible={isVisible}
onClose={() => setIsVisible(false)}
containerStyle={{
backgroundColor: '#f0f0f0',
borderTopLeftRadius: 30,
borderTopRightRadius: 30,
}}
>
Custom styled content
`
$3
`tsx
import { useState } from "react";
import {
KeyboardAvoidingView,
Platform,
Pressable,
ScrollView,
StyleSheet,
TextInput,
} from "react-native";
import { BottomSheet } from "szn-ui-react-native-bottom-sheet";
import { ThemedText } from "@/components/themed-text";
import { ThemedView } from "@/components/themed-view";
import ParallaxScrollView from "@/components/parallax-scroll-view";
import { Image } from "expo-image";
import { HelloWave } from "@/components/hello-wave";
export default function HomeScreen() {
const [isBottomSheetVisible, setIsBottomSheetVisible] = useState(false);
const [inputValue, setInputValue] = useState("");
const openBottomSheet = () => setIsBottomSheetVisible(true);
const closeBottomSheet = () => setIsBottomSheetVisible(false);
return (
<>
headerBackgroundColor={{ light: "#A1CEDC", dark: "#1D3D47" }}
headerImage={
source={require("@/assets/images/partial-react-logo.png")}
style={styles.reactLogo}
/>
}
>
Welcome!
Open Bottom Sheet
behavior={Platform.OS === "ios" ? "padding" : undefined}
style={{ flex: 1 }}
>
Bottom Sheet Test
Your bottom sheet package is working!
placeholder="Type something here..."
value={inputValue}
onChangeText={setInputValue}
style={styles.textInput}
placeholderTextColor="#999"
/>
Close
>
);
}
const styles = StyleSheet.create({
titleContainer: {
flexDirection: "row",
alignItems: "center",
gap: 8,
},
stepContainer: {
gap: 8,
marginBottom: 8,
},
reactLogo: {
height: 178,
width: 290,
bottom: 0,
left: 0,
position: "absolute",
},
bottomSheetButton: {
backgroundColor: "#007AFF",
paddingHorizontal: 20,
paddingVertical: 12,
borderRadius: 8,
alignItems: "center",
marginVertical: 20,
},
buttonText: {
color: "#FFFFFF",
fontWeight: "600",
},
bottomSheetContent: {
padding: 20,
alignItems: "center",
gap: 16,
},
textInput: {
width: "100%",
paddingHorizontal: 16,
paddingVertical: 12,
borderRadius: 8,
borderWidth: 1,
borderColor: "#ccc",
color: "#000",
},
closeButton: {
backgroundColor: "#FF3B30",
paddingHorizontal: 20,
paddingVertical: 10,
borderRadius: 6,
alignItems: "center",
},
});
``