Bottom Sheet
.mdDraggable glass sheet with snap points; release velocity is projected forward to pick the detent and the scrim fades with the sheet's height.
bottom sheetdrawersheetmodalmobiledragsnap pointsdetentsglass
Installation
$npx shadcn@latest add @geturui/bottom-sheet
Usage
usage.tsx
1"use client";
2import * as React from "react";
3import { BottomSheet } from "@/components/ui/bottom-sheet";
4
5export function TripDetails() {
6 const [open, setOpen] = React.useState(false);
7 return (
8 <>
9 <button onClick={() => setOpen(true)}>Show trip details</button>
10 <BottomSheet
11 open={open}
12 onOpenChange={setOpen}
13 snapPoints={[0.25, 0.55, 0.9]}
14 defaultSnap={1}
15 title="Your ride to GetUrUI HQ"
16 description="Arriving in 4 min"
17 >
18 <p>Driver, stops and fare go here.</p>
19 </BottomSheet>
20 </>
21 );
22}
Props
| Prop | Type | Default | Description |
|---|---|---|---|
open* | boolean | — | Whether the sheet is shown. |
onOpenChange* | (open: boolean) => void | — | Called on Escape, scrim press or a dismissing swipe. |
snapPoints | number[] | [0.25, 0.55, 0.9] | Detents as ascending fractions of the container height. |
defaultSnap | number | 1 | Detent index used each time the sheet opens. |
snap | number | — | Controlled detent index. |
onSnapChange | (index: number) => void | — | Called when the sheet settles on a new detent. |
title | ReactNode | — | Heading; labels the dialog. |
description | ReactNode | — | Supporting line; describes the dialog. |
dismissible | boolean | true | Allow closing by swiping below the lowest detent or pressing the scrim. |
contained | boolean | false | Fill the nearest positioned parent instead of the viewport, without scroll lock. |
className | string | — | Classes for the sheet surface. |
Accessibility
- role="dialog" (aria-modal when not contained) labelled by the title; focus moves to the sheet on open and returns to the opener on close.
- Escape closes. The handle is a button: Up and Down step through detents (Down from the lowest closes), Enter or Space cycles.
- Body scroll is locked while a viewport sheet is open; the content area scrolls on its own with overscroll containment.
- With reduced motion the sheet moves with short tweens instead of springs.