What is Drawer?

Drawer: A drawer is a panel that slides in from an edge of the screen over the page, used for navigation, filters or quick actions, and slides back when dismissed.

A drawer is a panel anchored to one edge of the viewport that slides into view on demand. The navigation drawer behind a hamburger button slides from the left; a bottom sheet of actions slides up from the bottom on phones; a filter drawer slides in from the right over a product list. Unlike a modal dialog, which floats in the center and interrupts, a drawer stays attached to the edge it came from, holds more content, and feels like a part of the page that was folded away.

Drawer or modal

  • Use a drawer for content that is long, scrollable or secondary to the page: navigation, filters, a settings panel, a list of actions on a phone.
  • Use a modal for a short decision or a small form that needs the user's full attention before anything else happens.
  • On phones, a bottom drawer usually beats a centered modal. It sits where the thumb is, can be dragged to a comfortable height, and keeps the page visible above it as context.
  • Neither for content people must read. Put it on the page.

A drawer can be modal, with a scrim that blocks the page behind, or non-modal, where the page stays usable, as with a persistent navigation rail on wide screens. Decide which, because the accessibility rules follow from it.

Accessibility

A modal drawer is a dialog that happens to sit at an edge, so it follows the dialog pattern: role="dialog", aria-modal="true", an accessible name from its title, focus moved inside on open, a focus trap while open, Escape to close, and focus returned to the button that opened it. A non-modal drawer drops aria-modal, does not trap focus and uses no scrim; the open button simply carries aria-expanded.

  • Swipe to dismiss is a nice touch, but always keep a visible close button, since gestures are not available to everyone.
  • If the drawer can be dragged to several heights, make the height change reachable by keyboard too, or offer a single full height.
  • Lock page scroll while a modal drawer is open, and reserve the scrollbar gutter so the page does not jump.
  • Keep the slide short and respect prefers-reduced-motion.

How to build one in React

MiniDev's Drawer is a Sheet that defaults to the bottom edge. Pass open and onClose to control it, or leave them out and it renders its own trigger:

tsx
"use client"
import * as React from "react"
import { Drawer } from "@/components/ui/drawer"
import { Button } from "@/components/ui/button"

export function InvoiceActions() {
  const [open, setOpen] = React.useState(false)
  return (
    <>
      <Button variant="outline" aria-haspopup="dialog" aria-expanded={open} onClick={() => setOpen(true)}>
        Actions
      </Button>
      <Drawer open={open} onClose={() => setOpen(false)} title="Invoice INV-2041">
        <Button variant="ghost" className="w-full justify-start">Send reminder</Button>
        <Button variant="ghost" className="w-full justify-start">Download PDF</Button>
      </Drawer>
    </>
  )
}

Use side="left" for navigation and side="right" for details. MobileActionSheet and MobileNavDrawer are ready-made versions of the two most common drawers. All of them live in the overlays category.

DraweruiBottom drawer that slides a sheet up from the screen edge with a titled header, close button and scrolling body, capped at 80% of the viewport height.npx shadcn@latest add @minidev/drawerMobile Nav DraweruiA hamburger button that opens a right side navigation drawer as a modal dialog, with a close button and links that dismiss it on tap. Built in React.npx shadcn@latest add @minidev/mobile-nav-drawer