Bottom Sheet
iOS-style bottom sheet: snap points, swipe, peek mode. Free, MIT · Overlays and notifications › Dialogs and panels
iOS-style sheet with snap points. Drag the handle, header or (at lower heights) the content; a flick moves on to the next height or closes it. The content scrolls only at the highest snap point, and pulling down from its top drags the sheet again.
Installation
npx valyro-cli@latest add bottom-sheet
npx shadcn@latest add https://valyro.xyz/r/bottom-sheet.json
npm install valyro-ui
import 'valyro-ui/styles.css';
import { BottomSheet } from 'valyro-ui';
Props
| Prop | Type | Default | |
|---|---|---|---|
open | boolean | Controlled open; use with onOpenChange. | |
defaultOpen | boolean | false | Initial open when uncontrolled. |
onOpenChange | (open: boolean) => void | Called with the new open when it changes. | |
snapPoints | SnapPoint[] | ['50%', '92%'] | Heights the sheet rests at, lowest first: px (320 or '320px') or a share of the available height ('50%'). Default ['50%', '92%'] — iOS medium and large detents. |
snap | number | Index of the current snap point (controlled). | |
defaultSnap | number | 0 | Snap point the sheet opens at (default 0, the lowest). |
onSnapChange | (index: number) => void | Called with the new snap when it changes. | |
modal | boolean | true | true (default): backdrop, focus trap, page scroll lock. false: a "peek" sheet that leaves the page interactive, like the drawer of a maps app. |
dismissible | boolean | true | Can be closed by dragging below the lowest snap point, Escape or a backdrop press (default true). |
dimFrom | number | 0 | Snap index at which the backdrop is fully dimmed; it fades in below that (default 0). |
title | ReactNode | Heading in the draggable header; also the dialog's accessible name. | |
description | ReactNode | Text under the title; also the dialog's accessible description. | |
showHandle | boolean | true | Show the grab handle (default true). |
container | HTMLElement | null | Render inside this element (which should be position: relative; overflow: hidden) instead of over the viewport — for sheets inside a panel, map or device frame. | |
initialFocusRef | RefObject<HTMLElement | null> | Element focused when a modal sheet opens (default: the sheet itself). | |
labels | Partial<BottomSheetLabels> | Overrides for the built-in English text; keys left out keep their defaults. | |
children | ReactNode | Sheet body; it scrolls only at the highest snap point, otherwise dragging it moves the sheet. In the compound form, a BottomSheet.Trigger and a BottomSheet.Content (with .Header, .Title, .Description, .Body, .Close). |
Compound parts
BottomSheet.Trigger (BottomSheetTrigger), BottomSheet.Content (BottomSheetContent), BottomSheet.Header (BottomSheetHeader), BottomSheet.Title (BottomSheetTitle), BottomSheet.Description (BottomSheetDescription), BottomSheet.Body (BottomSheetBody), BottomSheet.Close (BottomSheetClose)
Related components
- Dialog — Modal dialogs
- Confirm Dialog — Action confirmation
- Drawer — Slide-out panels
- Alert — Inline alerts
- Toast — Pop-up notifications
- Notification Center — Notification inbox
- Loading Overlay — Loading screen
- Popover — Floating content
- Hover Card — Card on hover
- Tour — Onboarding tour: element spotlight, steps, progress and resume
Previous: Drawer · Next: Popover · All Overlays and notifications