reactnatively
BottomSheet
A gesture-driven bottom sheet with configurable snap points, backdrop dismissal, and an optional glass surface. Ideal for action menus, filters, and contextual detail panels.
Import
typescript
import { BottomSheet } from 'reactnatively';Action sheet
PostActions.tsx
1import { useState } from 'react';2import { View, TouchableOpacity, StyleSheet } from 'react-native';3import { Ionicons } from '@expo/vector-icons';4import { BottomSheet, Text, Button } from 'reactnatively';56const actions = [7 { icon: 'share-social-outline', label: 'Share post' },8 { icon: 'bookmark-outline', label: 'Save' },9 { icon: 'copy-outline', label: 'Copy link' },10 { icon: 'flag-outline', label: 'Report' },11];1213export function PostActions() {14 const [open, setOpen] = useState(false);1516 return (17 <>18 <Button variant="ghost" onPress={() => setOpen(true)}>19 More options20 </Button>21 <BottomSheet22 isOpen={open}23 onClose={() => setOpen(false)}24 snapPoints={[45]}25 title="Post actions"26 glass27 >28 <View style={styles.list}>29 {actions.map((action) => (30 <TouchableOpacity key={action.label} style={styles.row} onPress={() => setOpen(false)}>31 <Ionicons name={action.icon as any} size={22} color="rgba(255,255,255,0.7)" />32 <Text variant="md">{action.label}</Text>33 </TouchableOpacity>34 ))}35 </View>36 </BottomSheet>37 </>38 );39}4041const styles = StyleSheet.create({42 list: { paddingHorizontal: 20, paddingBottom: 32 },43 row: { flexDirection: 'row', alignItems: 'center', gap: 16, paddingVertical: 14 },44});Multi-snap detail panel
PlaceDetail.tsx
1import { useState } from 'react';2import { ScrollView, View, StyleSheet } from 'react-native';3import { BottomSheet, Heading, Text, Button, LiquidCardImage } from 'reactnatively';45export function MapWithSheet({ place }) {6 const [open, setOpen] = useState(false);78 return (9 <View style={styles.root}>10 {/* Map renders here */}11 <Button12 variant="glass"13 style={styles.trigger}14 onPress={() => setOpen(true)}15 >16 View Details17 </Button>1819 <BottomSheet20 isOpen={open}21 onClose={() => setOpen(false)}22 snapPoints={[40, 85]}23 initialSnap={0}24 glass25 showHandle26 >27 <ScrollView contentContainerStyle={styles.content}>28 <LiquidCardImage source={{ uri: place.photo }} height={180} rounded />29 <Heading level="h3" style={{ marginTop: 16 }}>{place.name}</Heading>30 <Text variant="sm" color="rgba(255,255,255,0.5)" style={{ marginTop: 4 }}>31 {place.address}32 </Text>33 <Text variant="md" color="rgba(255,255,255,0.7)" style={{ marginTop: 16, lineHeight: 24 }}>34 {place.description}35 </Text>36 <Button variant="solid" color="primary" fullWidth style={{ marginTop: 24 }}>37 Get Directions38 </Button>39 </ScrollView>40 </BottomSheet>41 </View>42 );43}4445const styles = StyleSheet.create({46 root: { flex: 1 },47 trigger: { position: 'absolute', bottom: 24, alignSelf: 'center' },48 content: { padding: 20, paddingBottom: 40 },49});Props
| Prop | Type | Default | Description |
|---|---|---|---|
| isOpen | boolean | — | Controls whether the sheet is visible. |
| onClose | () => void | — | Called when the sheet is dismissed. |
| snapPoints | number[] | [50] | Array of snap percentages (e.g. [50, 90]). Sheet snaps to these heights. |
| initialSnap | number | 0 | Index into snapPoints for the initial open height. |
| title | string | undefined | Optional title rendered in the sheet header. |
| children | ReactNode | undefined | Content rendered inside the sheet. |
| isDismissible | boolean | true | When false, prevents backdrop tap and swipe-down dismissal. |
| showHandle | boolean | true | Shows the drag handle pill at the top of the sheet. |
| glass | boolean | false | Renders the sheet surface with Liquid Glass. |
| style | StyleProp<ViewStyle> | undefined | Style applied to the sheet container. |