Drawer
A panel that slides in from the edge and follows the finger. Itโs made for phones and for details beside a list.
When to use it
Use Drawer for choices on a phone, where the thumb already is, and for side panels that show the details of something in a list.
On a large screen, a short centered task is usually better as a Dialog.
DrawerThis page
The page waits, from the edge.
Choices on a phone, details beside a list.
How it behaves
Drawer opens from the bottom by default; set swipeDirection to up, left, or right. Swiping toward that edge, an outside press, or Escape closes it, and Base UI traps focus and returns it to the trigger.
Always provide DrawerTitle and DrawerDescription. Close with a DrawerClose rendered as a Button: footer actions for a bottom drawer, or a ghost icon button with a Tooltip beside the title in a side drawer. Set showSwipeHandle on Drawer to show the grab handle.
Vertical drawers attach to the edge and fit their content up to 100dvh minus 6rem. Side drawers float 8px from the edges as a rounded card, 75% wide or 24rem from the sm breakpoint; set [--drawer-inset:0px] on DrawerContent to attach one to the edge. Override size with h-*, max-h-*, or w-*, and make a flex-1 child the scroll container.
The panel uses the overlay surface and the dialog shadow, which draws its own hairline edge, 20px header and footer padding, heading-16 and body-sm, and the iOS sheet curve. Reduced motion fades it in place instead of sliding; a swipe still follows the finger.
On iOS Safari, give body position: relative so the overlay covers the page after scrolling. Use Sheet for a desktop side panel and Dialog for a centered task.
Build it
Add it with the shadcn CLI:
1pnpm dlx shadcn@latest add https://jzbui.com/r/drawer.jsonA complete example. Change the values to fit your product:
12345678910111213141516171819202122232425262728import { Button } from "@/components/ui/button"import { Drawer, DrawerClose, DrawerContent, DrawerDescription, DrawerFooter, DrawerHeader, DrawerTitle, DrawerTrigger} from "@/components/ui/drawer"
<Drawer showSwipeHandle> <DrawerTrigger render={<Button />}>Move tasks</DrawerTrigger> <DrawerContent> <DrawerHeader> <DrawerTitle>Move 3 tasks</DrawerTitle> <DrawerDescription>Choose the project these tasks belong to.</DrawerDescription> </DrawerHeader> <div className="p-5">{/* Content */}</div> <DrawerFooter> <Button>Move tasks</Button> <DrawerClose render={<Button variant="secondary" />}>Cancel</DrawerClose> </DrawerFooter> </DrawerContent></Drawer>
// From the side: <Drawer swipeDirection="right">The full source is yours to edit once installed: