ToroUI

Drawer

A touch-friendly panel that slides in from any edge of the screen, built on Vaul.


A composable drawer component built on Vaul. It slides in from the bottom, top, left, or right edge of the viewport with a drag-to-dismiss gesture. A bottom drawer automatically renders a drag handle indicator.

import {
  Drawer,
  DrawerClose,
  DrawerContent,
  DrawerDescription,
  DrawerFooter,
  DrawerHeader,
  DrawerTitle,
  DrawerTrigger,
} from "@/components/ui/drawer"
import { Button } from "@/components/ui/button"

export default function DrawerDemo() {
  return (
    <Drawer>
      <DrawerTrigger asChild>
        <Button variant="outline">Open Drawer</Button>
      </DrawerTrigger>
      <DrawerContent>
        <DrawerHeader>
          <DrawerTitle>Move Goal</DrawerTitle>
          <DrawerDescription>Set your daily activity goal.</DrawerDescription>
        </DrawerHeader>
        <div className="p-4">
          <div className="flex items-center justify-center text-4xl font-bold">
            350
          </div>
          <p className="text-center text-sm text-muted-foreground">calories/day</p>
        </div>
        <DrawerFooter>
          <Button>Submit</Button>
          <DrawerClose asChild>
            <Button variant="outline">Cancel</Button>
          </DrawerClose>
        </DrawerFooter>
      </DrawerContent>
    </Drawer>
  )
}

Anatomy

import {
  Drawer,
  DrawerTrigger,
  DrawerContent,
  DrawerHeader,
  DrawerFooter,
  DrawerTitle,
  DrawerDescription,
  DrawerClose,
  DrawerOverlay,
  DrawerPortal,
} from "@/components/ui/drawer"
<Drawer>
  <DrawerTrigger>Open</DrawerTrigger>
  <DrawerContent>
    <DrawerHeader>
      <DrawerTitle>Title</DrawerTitle>
      <DrawerDescription>Description text.</DrawerDescription>
    </DrawerHeader>
    {/* Body content */}
    <DrawerFooter>
      <Button>Submit</Button>
      <DrawerClose>Cancel</DrawerClose>
    </DrawerFooter>
  </DrawerContent>
</Drawer>

Examples

Bottom drawer

The default direction. A drag handle is rendered automatically at the top.

<Drawer>
  <DrawerTrigger render={<Button />}>Open Drawer</DrawerTrigger>
  <DrawerContent>
    <DrawerHeader>
      <DrawerTitle>Notifications</DrawerTitle>
      <DrawerDescription>You have 3 unread messages.</DrawerDescription>
    </DrawerHeader>
    <DrawerFooter>
      <Button>Mark all as read</Button>
    </DrawerFooter>
  </DrawerContent>
</Drawer>

Right-side drawer

Pass direction="right" to the root to slide in from the right. Constrained to sm:max-w-sm.

<Drawer direction="right">
  <DrawerTrigger render={<Button />}>Settings</DrawerTrigger>
  <DrawerContent>
    <DrawerHeader>
      <DrawerTitle>Settings</DrawerTitle>
      <DrawerDescription>Manage your preferences.</DrawerDescription>
    </DrawerHeader>
    <div className="p-4">
      <p>Settings content goes here.</p>
    </div>
  </DrawerContent>
</Drawer>

Left-side drawer

Pass direction="left" for navigation-style drawers.

<Drawer direction="left">
  <DrawerTrigger render={<Button variant="outline" />}>Menu</DrawerTrigger>
  <DrawerContent>
    <DrawerHeader>
      <DrawerTitle>Navigation</DrawerTitle>
    </DrawerHeader>
    <nav className="flex flex-col gap-2 p-4">
      <a href="/dashboard">Dashboard</a>
      <a href="/settings">Settings</a>
    </nav>
  </DrawerContent>
</Drawer>

API Reference

Drawer

The root component that manages open/close state and slide direction. Wraps Vaul's Drawer.Root.

PropTypeDefaultDescription
direction"bottom" | "top" | "left" | "right""bottom"The edge the drawer slides in from.
openbooleanControlled open state.
onOpenChange(open: boolean) => voidCallback when the open state changes.
childrenReactNode

DrawerTrigger

The element that opens the drawer when clicked. Wraps Vaul's Drawer.Trigger.

PropTypeDefault
classNamestring
childrenReactNode

DrawerContent

The sliding panel rendered in a portal with an overlay. Adapts its position, rounding, and border based on the drawer direction.

PropTypeDefault
classNamestring
childrenReactNode

DrawerHeader

A <div> for the title and description. Centered for top/bottom drawers, left-aligned for side drawers on md+.

PropTypeDefault
classNamestring
childrenReactNode

DrawerFooter

A <div> pinned to the bottom of the drawer via mt-auto.

PropTypeDefault
classNamestring
childrenReactNode

DrawerTitle

The drawer heading. Wraps Vaul's Drawer.Title.

PropTypeDefault
classNamestring
childrenReactNode

DrawerDescription

Secondary text below the title. Wraps Vaul's Drawer.Description.

PropTypeDefault
classNamestring
childrenReactNode

DrawerClose

An element that closes the drawer when clicked. Wraps Vaul's Drawer.Close.

PropTypeDefault
classNamestring
childrenReactNode

DrawerOverlay

The backdrop behind the drawer. Renders with a blurred, semi-transparent background.

PropTypeDefault
classNamestring

DrawerPortal

Portals the drawer content to the end of document.body. Wraps Vaul's Drawer.Portal.

PropTypeDefault
childrenReactNode