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:
"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.