Drawer

A temporary side surface for focused work.

pnpm dlx shadcn@latest add @uiarc/drawer
Live · keyboard ready
  • Side panels for filters, settings, or record details that keep the page in context.
  • Forms that are too long for a dialog but should not leave the current view.
  • Panels from any edge, via side, with drag-to-dismiss on the header.
  • Use dialog for short decisions and confirmations.
  • Use bottom-sheet for mobile-first sheets with snap points.
  • Use popover for small anchored content that does not need a modal overlay.

Installation

Add Drawer with the shadcn CLI, or copy the source by hand.

pnpm dlx shadcn@latest add @uiarc/drawer

Adds the component and its local dependencies, and installs @radix-ui/react-dialog, motion, lucide-react. First time? Add the @uiarc registry to components.json, or use the full URL:

example.tsx
import { Drawer, DrawerTrigger, DrawerContent, DrawerClose } from "@/registry/components/drawer/drawer";import { Button } from "@/registry/components/button/button"; export function FiltersDrawer() {  return (    <Drawer>      <DrawerTrigger asChild><Button variant="secondary">Filters</Button></DrawerTrigger>      <DrawerContent title="Filters" description="Narrow the list of projects.">        <FilterForm />        <DrawerClose asChild><Button>Apply</Button></DrawerClose>      </DrawerContent>    </Drawer>  );}

API reference

4 parts. The first is the root.

Drawer

Root. A Radix Dialog root that keeps the panel mounted while it slides out and closes it after a drag.

PropTypeDefaultDescription
openboolean–Controlled open state.
defaultOpenbooleanfalseInitial state when uncontrolled.
onOpenChange(open: boolean) => void–Called when the drawer opens or closes.
...propsComponentPropsWithoutRef<typeof DialogPrimitive.Root>–Other Radix Dialog root props, such as modal and children.

DrawerTrigger

Radix Dialog.Trigger. Use asChild to wrap your own button.

PropTypeDefaultDescription
...propsComponentPropsWithoutRef<typeof DialogPrimitive.Trigger>–Radix trigger props, including asChild.

DrawerContent

Overlay and panel with a titled header that doubles as the drag handle, a close button, and a scrolling body.

PropTypeDefaultDescription
titleRequiredstring–Rendered as the dialog title. A new title rises in while open.
descriptionstring–Rendered as the dialog description under the title.
side"left" | "right" | "top" | "bottom""right"Edge the panel attaches to and slides from.
childrenRequiredReactNode–Body content.
...propsComponentPropsWithoutRef<typeof DialogPrimitive.Content>–Radix content props such as className, onInteractOutside, and onEscapeKeyDown.

DrawerClose

Radix Dialog.Close for extra close buttons in the body or footer.

PropTypeDefaultDescription
...propsComponentPropsWithoutRef<typeof DialogPrimitive.Close>–Radix close props, including asChild.
Escape
Closes the drawer and returns focus to the trigger.
TaborShift+Tab
Cycles focus within the panel while it is open.
  • Radix Dialog provides role="dialog", aria-modal, focus trapping, and focus return.
  • title and description are wired to Dialog.Title and Dialog.Description, so the panel is always named.
  • The header close button is labelled "Close drawer"; dragging is optional and never the only way to close.
  • The panel springs in from its edge and leaves faster on a tween; a drag past a third of the panel or a quick flick closes it and keeps the release velocity.
  • Dragging the header away from the edge rubber-bands; the overlay fades in and out.
  • Reduced motion disables dragging and replaces the slide with a short opacity fade.
  • Left and right panels are min(30rem, 100vw minus a gutter) wide; below 40rem they grow to nearly full width with tighter padding.
  • Top and bottom panels span the full width and cap at min(32rem, 100dvh).
  • The header is the drag handle with touch-action none, so a touch drag moves the panel while the body still scrolls normally.
  • The overlay uses a 4px backdrop blur, which can cost frames on low-end devices over busy pages.
  • Drag runs on motion pan handlers with no React re-render per frame; the panel stays mounted only while sliding out.

Notes for AI

Give your coding assistant the Markdown reference instead of screenshots.

  • Use for side panels with forms, filters, settings, or detail views that keep the page in context. Use dialog for short decisions and bottom-sheet for mobile-first sheets.
  • Always compose Drawer as the root; under a bare Radix Dialog root the panel falls back to CSS keyframes and loses drag.
  • Control open when the drawer must close after an async submit.
/components/drawer/markdown

The full library index for assistants is at /llms.txt.