react-native-step-bottom-sheet
Version:
A customizable step-by-step bottom sheet component for React Native with smooth animations
302 lines (248 loc) • 8.87 kB
Markdown
# React Native Step Bottom Sheet
A customizable step-by-step bottom sheet component for React Native with smooth animations, perfect for onboarding flows, wizards, and multi-step forms.
## Features
- 🎯 **Step-by-step navigation** with smooth animations
- 🎨 **Fully customizable** styling and behavior
- 📱 **Built on @gorhom/bottom-sheet** for reliable performance
- ⚡ **Dynamic height adjustment** based on content
- 🎭 **Animated transitions** between steps
- 🎮 **Gesture support** with pan-to-close functionality
- 🔧 **TypeScript support** with full type definitions
- 🎪 **Flexible step components** - use any React component as a step
## Installation
```bash
npm install react-native-step-bottom-sheet
# or
yarn add react-native-step-bottom-sheet
```
### Peer Dependencies
Make sure you have these peer dependencies installed:
```bash
npm install @gorhom/bottom-sheet react-native-gesture-handler react-native-reanimated react-native-safe-area-context
# or
yarn add @gorhom/bottom-sheet react-native-gesture-handler react-native-reanimated react-native-safe-area-context
```
## Quick Start
### App Setup
**Important:** Before using the component, you need to set up the required providers in your app's root layout.
#### For Expo Router Apps
Add the providers to your `app/_layout.tsx`:
```tsx
import { Slot } from "expo-router";
import { GestureHandlerRootView } from "react-native-gesture-handler";
import { BottomSheetModalProvider } from "@gorhom/bottom-sheet";
export default function Layout() {
return (
<GestureHandlerRootView style={{ flex: 1 }}>
<BottomSheetModalProvider>
<Slot />
</BottomSheetModalProvider>
</GestureHandlerRootView>
);
}
```
#### For React Navigation Apps
Add the providers to your `App.tsx` or root component:
```tsx
import React from 'react';
import { NavigationContainer } from '@react-navigation/native';
import { GestureHandlerRootView } from 'react-native-gesture-handler';
import { BottomSheetModalProvider } from '@gorhom/bottom-sheet';
import YourNavigator from './YourNavigator';
export default function App() {
return (
<GestureHandlerRootView style={{ flex: 1 }}>
<NavigationContainer>
<BottomSheetModalProvider>
<YourNavigator />
</BottomSheetModalProvider>
</NavigationContainer>
</GestureHandlerRootView>
);
}
```
### Basic Usage
```tsx
import React, { useRef, useCallback } from 'react';
import { View, Text, TouchableOpacity } from 'react-native';
import { GestureHandlerRootView } from 'react-native-gesture-handler';
import BottomSheet from '@gorhom/bottom-sheet';
import { StepBottomSheet } from 'react-native-step-bottom-sheet';
// Define your step components
const WelcomeStep = () => (
<View style={{ padding: 20 }}>
<Text style={{ fontSize: 24, fontWeight: 'bold' }}>Welcome! 🎉</Text>
<Text>Get started with our amazing app</Text>
</View>
);
const SetupStep = () => (
<View style={{ padding: 20 }}>
<Text style={{ fontSize: 24, fontWeight: 'bold' }}>Setup 🔧</Text>
<Text>Let's configure your preferences</Text>
</View>
);
const ReadyStep = () => (
<View style={{ padding: 20 }}>
<Text style={{ fontSize: 24, fontWeight: 'bold' }}>Ready! 🚀</Text>
<Text>You're all set to begin</Text>
</View>
);
const App = () => {
const bottomSheetRef = useRef<BottomSheet>(null);
const steps = [WelcomeStep, SetupStep, ReadyStep];
const handleOpenPress = useCallback(() => {
bottomSheetRef.current?.snapToIndex(0);
}, []);
const handleClosePress = useCallback(() => {
bottomSheetRef.current?.close();
}, []);
return (
<GestureHandlerRootView style={{ flex: 1, backgroundColor: "gray" }}>
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<TouchableOpacity onPress={handleOpenPress}>
<Text>Open</Text>
</TouchableOpacity>
</View>
<StepBottomSheet
ref={bottomSheetRef}
steps={steps}
onClose={handleClosePress}
/>
</GestureHandlerRootView>
);
};
```
### Advanced Usage with Custom Styling
```tsx
import React from 'react';
import { View, Button } from 'react-native';
import { StepBottomSheet, useStepBottomSheet } from 'react-native-step-bottom-sheet';
const App = () => {
const { ref, open, close, currentStep } = useStepBottomSheet();
const handleStepChange = (stepIndex: number) => {
console.log('Current step:', stepIndex);
};
return (
<View style={{ flex: 1 }}>
<Button title="Open Custom Steps" onPress={open} />
<StepBottomSheet
ref={ref}
steps={[WelcomeStep, SetupStep, ReadyStep]}
onClose={close}
onStepChange={handleStepChange}
stepContentProps={{
initialStep: 0,
showNavigation: true,
showIndicators: true,
navigationLabels: {
previous: 'Back',
next: 'Continue'
},
styles: {
container: {
backgroundColor: '#f8f9fa',
borderTopLeftRadius: 20,
borderTopRightRadius: 20,
},
navigationButton: {
backgroundColor: '#007AFF',
borderRadius: 12,
},
stepIndicatorActive: {
backgroundColor: '#007AFF',
}
}
}}
snapPoints={['90%']}
enablePanDownToClose={true}
backdropProps={{
opacity: 0.5,
}}
/>
</View>
);
};
```
## API Reference
### StepBottomSheet Props
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| `steps` | `React.ComponentType[]` | **Required** | Array of React components to render as steps |
| `onClose` | `() => void` | `undefined` | Callback when bottom sheet is closed |
| `onStepChange` | `(stepIndex: number) => void` | `undefined` | Callback when step changes |
| `stepContentProps` | `Partial<StepContentProps>` | `{}` | Props to pass to the StepContent component |
| `snapPoints` | `string[]` | `["100%"]` | Bottom sheet snap points |
| `enablePanDownToClose` | `boolean` | `true` | Enable pan down to close gesture |
| `enableDynamicSizing` | `boolean` | `true` | Enable dynamic sizing based on content |
| `backdropProps` | `object` | `{}` | Props for the backdrop component |
### StepContentProps
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| `steps` | `React.ComponentType[]` | **Required** | Array of step components |
| `onClose` | `() => void` | `undefined` | Close callback |
| `onStepChange` | `(stepIndex: number) => void` | `undefined` | Step change callback |
| `initialStep` | `number` | `0` | Initial step index |
| `showNavigation` | `boolean` | `true` | Show navigation buttons |
| `showIndicators` | `boolean` | `true` | Show step indicators |
| `navigationLabels` | `{previous: string, next: string}` | `{previous: 'Previous', next: 'Next'}` | Navigation button labels |
| `styles` | `object` | `{}` | Custom styles object |
### useStepBottomSheet Hook
Returns an object with:
| Property | Type | Description |
|----------|------|-------------|
| `ref` | `RefObject` | Ref to pass to StepBottomSheet |
| `open` | `() => void` | Function to open the bottom sheet |
| `close` | `() => void` | Function to close the bottom sheet |
| `goToStep` | `(stepIndex: number) => void` | Function to navigate to specific step |
| `currentStep` | `number` | Current step index |
| `isOpen` | `boolean` | Whether the bottom sheet is open |
## Styling
The component supports extensive styling customization through the `styles` prop in `stepContentProps`:
```tsx
const customStyles = {
container: {
backgroundColor: '#ffffff',
borderTopLeftRadius: 30,
borderTopRightRadius: 30,
},
navigationButton: {
backgroundColor: '#007AFF',
paddingHorizontal: 24,
paddingVertical: 12,
borderRadius: 8,
},
navigationButtonDisabled: {
backgroundColor: '#E5E5E5',
},
navigationButtonText: {
color: 'white',
fontSize: 16,
fontWeight: '600',
},
navigationButtonTextDisabled: {
color: '#999',
},
stepIndicator: {
width: 10,
height: 10,
borderRadius: 5,
backgroundColor: '#E5E5E5',
},
stepIndicatorActive: {
backgroundColor: '#007AFF',
},
};
```
## Examples
Check out the `/example` folder for complete working examples including:
- Basic step navigation
- Custom styling
- Dynamic content
- Integration with forms
- Onboarding flows
## Contributing
Contributions are welcome! Please read our contributing guidelines and submit pull requests to our repository.
## License
MIT License - see LICENSE file for details.
## Credits
Built on top of the excellent [@gorhom/bottom-sheet](https://github.com/gorhom/react-native-bottom-sheet) library.