Bottom Sheet
An interactive bottom sheet with snap points, gestures, scroll coordination, and keyboard support.
Bottom Sheet wraps @gorhom/bottom-sheet with a compound component API similar to Native Sheet. It is the recommended sheet component for new projects—whether you need draggable snap points, scrollable content, keyboard-aware forms, or a simple modal sheet.

Installation
npx shadcn@latest add @tetra-ui/bottom-sheetUsage
import { Button, ButtonText } from "@/components/ui/button";
import {
BottomSheet,
BottomSheetBody,
BottomSheetClose,
BottomSheetContent,
BottomSheetFooter,
BottomSheetHeader,
BottomSheetOverlay,
BottomSheetPortal,
BottomSheetTitle,
BottomSheetTrigger,
} from "@/components/ui/bottom-sheet";<BottomSheet>
<BottomSheetTrigger asChild>
<Button>
<ButtonText>Open</ButtonText>
</Button>
</BottomSheetTrigger>
<BottomSheetPortal>
<BottomSheetOverlay />
<BottomSheetContent>
<BottomSheetHeader>
<BottomSheetTitle>Bottom Sheet Title</BottomSheetTitle>
</BottomSheetHeader>
<BottomSheetBody>
<Text className="text-foreground">Bottom Sheet Body</Text>
</BottomSheetBody>
<BottomSheetFooter>
<BottomSheetClose asChild>
<Button>
<ButtonText>Close</ButtonText>
</Button>
</BottomSheetClose>
</BottomSheetFooter>
</BottomSheetContent>
</BottomSheetPortal>
</BottomSheet>Snap points
Pass fractional values (0.4 → 40%), pixel numbers, or percentage strings to BottomSheetContent:
<BottomSheetContent snapPoints={[0.35, 0.65, 1]} defaultSnapIndex={1}>
{/* ... */}
</BottomSheetContent>Scrollable content
Use BottomSheetScrollView for long lists so scrolling does not conflict with sheet drag gestures. Place BottomSheetHeader as a sibling above the scroll view — it stays pinned at the top while content scrolls beneath it (same pattern as BottomSheetFooter):
<BottomSheetContent snapPoints={[0.5, 0.9]}>
<BottomSheetHeader>
<BottomSheetTitle>List</BottomSheetTitle>
</BottomSheetHeader>
<BottomSheetScrollView>
{/* scrollable items */}
</BottomSheetScrollView>
</BottomSheetContent>Keyboard
With snap points configured, call useBottomSheetInputHandlers() inside the sheet and pass onFocus / onBlur to inputs. The sheet expands to the highest snap while focused:
function SheetForm() {
const { onFocus, onBlur } = useBottomSheetInputHandlers();
return (
<TextInput onFocus={onFocus} onBlur={onBlur} placeholder="Message" />
);
}Bottom Sheet vs Native Sheet
| Feature | Bottom Sheet | Native Sheet |
|---|---|---|
| Foundation | @gorhom/bottom-sheet | React Native Modal |
| Snap points | Yes | No |
| Drag to resize / dismiss | Yes | No |
| Scroll coordination | BottomSheetScrollView | Manual |
| Keyboard awareness | Yes | No |
| Overlay opacity vs expansion | Animated with snap index | Fade with open state |
| Sticky footer | BottomSheetFooter | NativeSheetFooter |
| Best for | Interactive sheets, forms, lists | Simple dialogs, selects |
Changelog
2026-05-25 Initial release
- Compound API:
BottomSheet,BottomSheetPortal,BottomSheetOverlay,BottomSheetContent, and layout primitives - Snap points, pan-down-to-close, dynamic sizing
BottomSheetScrollView, stickyBottomSheetFooter,useBottomSheetInputHandlers