docs / core / drawer
Drawer
the same anatomy as Dialog, pinned to an edge instead of centered. a panel slides in from any side; a bottom sheet is just side="bottom".
intensity · recedesrsc · client
provenance
shaped from personal-website · sisu-pluslayer
core / primitivesintensity
recedes · safe anywhere, including dense surfacescomposition
settings panels, widget libraries, filters that keep the page visible behind the scrimthe slide-up sheet is this primitive with side="bottom"not navigation chrome. a persistent sidebar is layout, not a Drawernever two edges open at oncea11y
role="dialog" named by its Title · focus is trapped, Escape closes · Drawer.Close keeps a 44px minimum targetjest-axedependencies
@base-ui/react · Card from the same packagelive demo · try it out
customize
sidewhich edge it pins to
sizeinline size, or block size on horizontal edges
surfacehow the panel sits above the scrim
highlightwash, inner edge, or glow ring
titlethe heading that names the dialog
descriptionsupporting line under the title
usage
import { Button } from "@usva-ui/react/primitives/button";
import { Drawer } from "@usva-ui/react/primitives/drawer";
<Drawer>
<Drawer.Trigger render={<Button>Open</Button>} />
<Drawer.Content>
<Drawer.Title>Widget library</Drawer.Title>
<Drawer.Description>Drag a widget onto the grid to add it.</Drawer.Description>
<Drawer.Close render={<Button variant="ghost">Done</Button>} />
</Drawer.Content>
</Drawer>props
| prop | type | default | notes |
|---|---|---|---|
| side | "top" | "right" | "bottom" | "left" | "right" | which edge the panel is pinned to. |
| size | "sm" | "md" | "lg" | "md" | inline size on the vertical edges, block size on the horizontal ones. |
| surface | "elevated" | "flat" | "glass" | "elevated" | how the panel sits above the scrim. shared with Card and Dialog. |
| highlight | "none" | "wash" | "edge" | "ring" | "none" | accent treatment on Drawer.Content: a wash, a top edge hairline, or a glow ring. the same vocabulary as Card and Dialog. |
| backdropClassName | string | — | extra classes on the scrim, on Drawer.Content. |
get it
bun add @usva-ui/reactusage
import { Button } from "@usva-ui/react/primitives/button";
import { Drawer } from "@usva-ui/react/primitives/drawer";
<Drawer>
<Drawer.Trigger render={<Button>Edit layout</Button>} />
<Drawer.Content side="right" size="md">
<Drawer.Title>Widget library</Drawer.Title>
<Drawer.Description>Drag a widget onto the grid.</Drawer.Description>
<Drawer.Close render={<Button variant="ghost">Done</Button>} />
</Drawer.Content>
</Drawer>