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

PropTypeDefaultDescription
isOpenbooleanControls whether the sheet is visible.
onClose() => voidCalled when the sheet is dismissed.
snapPointsnumber[][50]Array of snap percentages (e.g. [50, 90]). Sheet snaps to these heights.
initialSnapnumber0Index into snapPoints for the initial open height.
titlestringundefinedOptional title rendered in the sheet header.
childrenReactNodeundefinedContent rendered inside the sheet.
isDismissiblebooleantrueWhen false, prevents backdrop tap and swipe-down dismissal.
showHandlebooleantrueShows the drag handle pill at the top of the sheet.
glassbooleanfalseRenders the sheet surface with Liquid Glass.
styleStyleProp<ViewStyle>undefinedStyle applied to the sheet container.