Overview

A headless bottom sheet engine for React Native — Gesture Handler for the pans, Reanimated for the motion, keyboard-controller for the keyboard, teleport for the portal.

@delacour/react-native-bottom-sheet moves a sheet and nothing else. Every radius, colour and inset is a style you pass in: there is no className, no token and no theme. The skinned BottomSheet in @delacour/react-native-ui is this engine with the theme attached, and it is the one to reach for when you want a sheet that already matches the rest of the library.

import { BottomSheet } from "@delacour/react-native-bottom-sheet";
import { Text, View } from "react-native";

<BottomSheet snapPoints={["40%", "85%"]} dynamicSizing={false}>
  <BottomSheet.Trigger style={styles.button}>
    <Text style={styles.buttonLabel}>Open</Text>
  </BottomSheet.Trigger>
  <BottomSheet.Portal>
    <BottomSheet.Overlay style={styles.overlay} />
    <BottomSheet.Container>
      <BottomSheet.Background style={styles.background} />
      <BottomSheet.Handle style={styles.handle}>
        <View style={styles.pill} />
      </BottomSheet.Handle>
      <BottomSheet.Content style={styles.content}>
        <BottomSheet.Title style={styles.title}>Two snap points</BottomSheet.Title>
        <BottomSheet.Description style={styles.description}>
          Drag the handle up for the second. Drag past the first to close.
        </BottomSheet.Description>
        <BottomSheet.Close style={styles.close}>
          <Text style={styles.closeLabel}>Close</Text>
        </BottomSheet.Close>
      </BottomSheet.Content>
    </BottomSheet.Container>
  </BottomSheet.Portal>
</BottomSheet>;

A sheet is a root and the parts you place inside it. The root owns the state — where the sheet is, which snap points it may rest at, whose keyboard it is lifting for — and publishes it through a context; a part reads that context and renders one thing. Composition lays the parts out and names every prop.

What it does

Where it draws

Reference

What is not here

A className. A colour token. A GestureHandlerRootView, a SafeAreaProvider or a KeyboardProvider — your app has all three already, and a nested KeyboardProvider is a second, disagreeing keyboard. A BottomSheetModal component: a modal sheet is a sheet whose portal teleports, and that is the default. The reasoning behind each is in the package's own AGENTS.md.

On this page