BottomSheet
Mobile bottom sheet with drag-to-resize detents, velocity-projected snapping, and drag-to-dismiss
Category: overlay · WCAG 2.2-AA · overlay, sheet, bottom-sheet, mobile, drag, detent, gesture
States
- open
- closed
- dragging
Props
| Prop | Type | Default | Description |
|---|---|---|---|
open | boolean | — | Whether the component is open (controlled). |
defaultOpen | boolean | — | Whether the component is open on first render (uncontrolled). |
onOpenChange | (open: boolean) => void | — | Called with the next open state when it changes. |
snapPoints | number[] | [0.5, 0.92] | Detent heights as ascending fractions of the viewport (0–1) |
activeSnap | number | — | The controlled snap-point index. |
defaultSnap | number | 0 | The initial snap-point index when uncontrolled. |
onSnapChange | (index: number) => void | — | Called with the new snap-point index when it changes. |
title | React.ReactNode | — | Title text for the component. |
description | React.ReactNode | — | Supporting description text. |
children | React.ReactNode | — | Content rendered inside the component. |
labels | { close?: string; handle?: string } | — | Overrides for the component’s user-visible strings (i18n). |
className | string | — | Additional CSS class names merged onto the root element. |
Design tokens
--cascivo-color-surface--cascivo-color-border--cascivo-radius-overlay--cascivo-shadow-overlay--cascivo-motion-enter--cascivo-motion-exit--cascivo-target-min-coarse--cascivo-z-overlay
When to use
- A mobile surface that rises from the bottom and can be resized between detents by dragging
- Showing secondary content, filters, or a form where the user can peek at half height then expand
- A touch-first overlay that dismisses by flinging or dragging it down past the lowest detent
When not to use
- A short yes/no confirmation — use AlertDialog
- A non-resizable edge panel without gestures — use Drawer or Sheet
- A desktop-first side panel for navigation — use Drawer
How to build an accessible BottomSheet in React →
Examples
Basic
<BottomSheet open={isOpen} onOpenChange={setIsOpen} title="Filters">
<FilterForm />
</BottomSheet>Custom detents
Snaps between three detents by dragging the handle; opens at half height.
<BottomSheet defaultOpen snapPoints={[0.25, 0.5, 0.9]} defaultSnap={1} title="Nearby">
<PlacesList />
</BottomSheet>