This documentation is available as Markdown for AI agents and LLMs. See the full Markdown index or append .md to any documentation URL.

BottomSheet

A modal sheet that slides up from the bottom of the screen.

Android
iOS
Web
Included in Expo Go
Recommended version:
~56.0.26

A modal sheet that slides up from the bottom of the screen. The sheet's visibility is controlled — toggle isPresented from React state and dismiss it from onDismiss (called when the user swipes down or taps the overlay).

Installation

Terminal
- npx expo install @expo/ui
- yarn expo install @expo/ui
- pnpm expo install @expo/ui
- bun expo install @expo/ui

If you are installing this in an existing React Native app, make sure to install expo in your project.

Usage

Basic bottom sheet

BottomSheetExample.tsx
import { useState } from 'react'; import { Host, Column, Button, BottomSheet, Text } from '@expo/ui'; export default function BottomSheetExample() { const [isPresented, setIsPresented] = useState(false); return ( <Host style={{ flex: 1 }}> <Button label="Open sheet" onPress={() => setIsPresented(true)} /> <BottomSheet isPresented={isPresented} onDismiss={() => setIsPresented(false)}> <Column spacing={12}> <Text textStyle={{ fontSize: 18, fontWeight: '700' }}>Sheet contents</Text> <Text>Drag down or tap the overlay to dismiss.</Text> <Button label="Close" onPress={() => setIsPresented(false)} /> </Column> </BottomSheet> </Host> ); }

Hiding the drag indicator

Pass showDragIndicator={false} for sheets without a handle.

BottomSheetNoIndicatorExample.tsx
import { useState } from 'react'; import { Host, Button, BottomSheet, Text } from '@expo/ui'; export default function BottomSheetNoIndicatorExample() { const [isPresented, setIsPresented] = useState(false); return ( <Host style={{ flex: 1 }}> <Button label="Open" onPress={() => setIsPresented(true)} /> <BottomSheet isPresented={isPresented} onDismiss={() => setIsPresented(false)} showDragIndicator={false}> <Text>No drag handle.</Text> </BottomSheet> </Host> ); }

Snap points

Pass snapPoints to let the user drag the sheet between multiple resting heights. You can use the semantic values 'half' and 'full' for cross-platform parity. The { fraction } and { height } forms are honored precisely on iOS and web.

When sheet content can be taller than the smallest snap point, wrap it in a ScrollView so the overflow scrolls correctly.

BottomSheetSnapPointsExample.tsx
import { useState } from 'react'; import { Host, BottomSheet, Button, Column, ScrollView, Text } from '@expo/ui'; export default function BottomSheetSnapPointsExample() { const [isPresented, setIsPresented] = useState(false); return ( <Host style={{ flex: 1 }}> <Button label="Open" onPress={() => setIsPresented(true)} /> <BottomSheet isPresented={isPresented} onDismiss={() => setIsPresented(false)} snapPoints={['half', 'full']}> <ScrollView> <Column spacing={12}> <Text textStyle={{ fontSize: 20, fontWeight: '700' }}>Half / full sheet</Text> <Text>Drag the sheet between half and full screen height.</Text> </Column> </ScrollView> </BottomSheet> </Host> ); }

Scrollable React Native content

The bottom sheet supports a React Native list such as FlatList (or a high-performance list like FlashList or Legend List) as a child when wrapped in RNHostView. snapPoints sizes the sheet, and the list scrolls within that height. With nestedScrollEnabled, the list scrolls its own content first; once it reaches the top edge, the remaining drag moves the sheet.

BottomSheetScrollableExample.tsx
import { useState } from 'react'; import { FlatList, Text } from 'react-native'; import { Host, BottomSheet, Button, RNHostView } from '@expo/ui'; const DATA = Array.from({ length: 50 }, (_, i) => `Item ${i + 1}`); export default function BottomSheetScrollableExample() { const [isPresented, setIsPresented] = useState(false); return ( <Host matchContents> <Button label="Open" onPress={() => setIsPresented(true)} /> <BottomSheet isPresented={isPresented} onDismiss={() => setIsPresented(false)} snapPoints={['half', 'full']}> <RNHostView> <FlatList nestedScrollEnabled style={{ flex: 1 }} data={DATA} keyExtractor={item => item} renderItem={({ item }) => <Text style={{ padding: 16 }}>{item}</Text>} /> </RNHostView> </BottomSheet> </Host> ); }

API

import { BottomSheet } from '@expo/ui';

No API data file found, sorry!