A React Native Expo app demonstrating the powerful React Native Modal Sheet component with multiple examples and interactive demos.
- π¨ Smooth Animations - Buttery smooth bezier easing with 60fps performance
- π― Snap Points - Multiple snap positions with intelligent detection
- π Scroll-to-Expand - Automatically expand to next snap point while scrolling
- π Pull-to-Collapse - Pull down at the top to collapse or close
- π― Zero Native Dependencies - Built with React Native's Animated API
- π± Cross Platform - Works on both iOS and Android
- π Backdrop Animation - Independent opacity animation for backdrop
- π Gesture Support - Drag to close with customizable threshold
- π¨ Fully Customizable - Customize colors, dimensions, and animations
- π¦ Lightweight - Minimal overhead, no external dependencies
- βΏ ARIA Compliant - Full accessibility support with ARIA attributes
- π TypeScript Support - Full TypeScript definitions included
- Node.js (v16 or higher)
- npm or yarn
- Expo CLI (
npm install -g @expo/cli) - Expo Go app on your device (iOS/Android)
- Clone the repository
git clone https://github.com/christi10/rn-modal-bottom-sheet.git
cd rn-modal-bottom-sheet- Install dependencies
npm install- Start the development server
npx expo start- Run on your device
- iOS: Press
iin terminal or scan QR code with Camera app - Android: Press
ain terminal or scan QR code with Expo Go app
- iOS: Press
The app includes three main sections:
- Welcome screen introducing ModalSheet
- Feature overview
- Quick navigation to examples
Interactive demonstrations of different modal sheet types:
- Action Buttons (300px) - Share, save, delete actions
- Form Input (450px) - Contact form with text inputs
- Scrollable List (600px) - Country selection with scrollable content
- Large Content (700px) - Terms of service with long text
- Small Sheet (200px) - Quick settings with icon buttons
- Drag & Drop List (550px) - Interactive draggable list
- Dynamic Sizing - Auto-sized sheets based on content
- Snap Points - 3 Points - Small (30%), Medium (60%), Large (90%) with scroll-to-expand
- Snap Points - 2 Points - Small (30%), Large (90%) simplified example
- Detailed information about bottom sheet features
- Component capabilities overview
This app demonstrates the rn-modal-bottom-sheet component with the following features:
import React, { useRef } from 'react';
import { Button, Text, View } from 'react-native';
import ModalSheet, { ModalSheetRef } from 'rn-modal-bottom-sheet';
function App() {
const sheetRef = useRef<ModalSheetRef>(null);
return (
<View style={{ flex: 1 }}>
<Button title="Open Sheet" onPress={() => sheetRef.current?.open()} />
<ModalSheet ref={sheetRef} height={400}>
<Text style={{ fontSize: 24, fontWeight: 'bold', textAlign: 'center' }}>
Hello Bottom Sheet! π
</Text>
</ModalSheet>
</View>
);
}| Prop | Type | Default | Description |
|---|---|---|---|
children |
ReactNode |
Required | Content to be rendered inside the bottom sheet |
height |
number |
400 |
Height of the bottom sheet in pixels |
snapPoints |
number[] |
- | Array of snap points as percentages (0-1) or pixels |
initialSnapIndex |
number |
0 |
Which snap point to open to initially |
enableScrollToExpand |
boolean |
true |
Enable scroll-to-expand behavior |
scrollExpandThreshold |
number |
50 |
Pixels to scroll before triggering transition |
onSnapPointChange |
(index: number) => void |
- | Callback when snap point changes |
onClose |
() => void |
- | Callback when the sheet is closed |
onOpen |
() => void |
- | Callback when the sheet is opened |
backgroundColor |
string |
'white' |
Background color of the sheet |
borderRadius |
number |
20 |
Border radius of the top corners |
showHandle |
boolean |
true |
Show the drag handle indicator |
handleColor |
string |
'#DDD' |
Color of the drag handle |
backdropOpacity |
number |
0.5 |
Opacity of the backdrop (0-1) |
dragThreshold |
number |
125 |
Distance to drag before sheet closes |
aria-label |
string |
'Bottom sheet' |
Accessible label for the modal |
aria-describedby |
string |
- | ID of element describing the modal |
backdropAriaLabel |
string |
'Close bottom sheet' |
Accessible label for backdrop |
| Method | Description |
|---|---|
open() |
Opens the bottom sheet |
close() |
Closes the bottom sheet |
present() |
Alias for open() |
dismiss() |
Alias for close() |
snapToPoint(index) |
Snap to a specific snap point by index |
handleScroll(event) |
Process scroll events for scroll-to-expand |
handleScrollBeginDrag(event) |
Track scroll start position |
handleScrollEndDrag(event) |
Handle pull-to-collapse gestures |
<ModalSheet
ref={sheetRef}
height={500}
backgroundColor="#1a1a1a"
borderRadius={30}
handleColor="#666"
backdropOpacity={0.8}
>
<Text style={{ color: 'white' }}>Dark Theme Sheet</Text>
</ModalSheet>import { useRef, useState } from 'react';
function MyComponent() {
const sheetRef = useRef<ModalSheetRef>(null);
const [currentIndex, setCurrentIndex] = useState(0);
return (
<ModalSheet
ref={sheetRef}
snapPoints={[0.3, 0.6, 0.9]} // 30%, 60%, 90% of screen height
initialSnapIndex={0}
onSnapPointChange={(index) => setCurrentIndex(index)}
>
<Text>Current snap point: {currentIndex}</Text>
</ModalSheet>
);
}import { ScrollView } from 'react-native';
<ModalSheet
ref={sheetRef}
snapPoints={[0.3, 0.9]}
enableScrollToExpand={true}
scrollExpandThreshold={20}
>
<ScrollView
onScroll={(e) => sheetRef.current?.handleScroll(e)}
onScrollBeginDrag={(e) => sheetRef.current?.handleScrollBeginDrag(e)}
onScrollEndDrag={(e) => sheetRef.current?.handleScrollEndDrag(e)}
scrollEventThrottle={16}
>
{/* Your scrollable content */}
</ScrollView>
</ModalSheet>import { ScrollView } from 'react-native';
<ModalSheet ref={sheetRef} height={600}>
<ScrollView showsVerticalScrollIndicator={false}>
{[...Array(50)].map((_, i) => (
<Text key={i} style={{ padding: 20 }}>Item {i + 1}</Text>
))}
</ScrollView>
</ModalSheet>The ModalSheet component is fully accessible and follows WCAG guidelines:
- β
ARIA Attributes - Modern
aria-label,aria-modal,aria-describedbysupport - β Screen Reader Support - Proper labeling and hints for all interactive elements
- β Voice Announcements - Announces when sheet opens/closes
- β Focus Management - Handles focus correctly when modal appears
- β Semantic Roles - Uses proper ARIA roles (dialog, button)
- β Gesture Alternatives - Touch alternatives for drag gestures
- Transform-Based: Uses
translateYtransforms instead of height changes - Native Driver: All animations run on the UI thread at 60fps
- Smooth Easing: Custom bezier curve (0.25, 0.1, 0.25, 1) for natural feel
- No Layout Recalculations: Content pre-rendered once, just repositioned
- Optimized Rendering: Efficient re-renders and memory management
- Lightweight: No external dependencies, minimal overhead
βββ app/ # Expo Router app directory
β βββ (tabs)/ # Tab navigation screens
β β βββ _layout.tsx # Tab navigator setup
β β βββ examples.tsx # Modal sheet examples
β β βββ explore.tsx # Info screen
β β βββ index.tsx # Home screen
β βββ _layout.tsx # Root layout
β βββ index.tsx # App entry point
βββ components/ # Reusable components
β βββ ui/ # UI components
β βββ themed-text.tsx # Themed text component
β βββ haptic-tab.tsx # Tab with haptic feedback
βββ constants/ # App constants
βββ hooks/ # Custom hooks
βββ assets/ # Images and icons
βββ react-native-modal-sheet/ # Modal sheet source code
# Start development server
npm start
# Run on Android
npm run android
# Run on iOS
npm run ios
# Run on web
npm run web
# Build for production
npx expo buildContributions are welcome! Please read our Contributing Guidelines before submitting pull requests.
If you find this project helpful, consider supporting its development:
Your support helps maintain and improve this project!
MIT Β© Christian
Made with β€οΈ using React Native & Expo