Drawer
An edge-anchored panel — the phone navigation, a filter sheet. The same <dialog> machinery as Modal with different geometry, so it inherits the same focus behaviour.
import Drawer from '@/components/ui/Drawer';Source: src/components/ui/Drawer.tsx
Examples
Sliding in from the edge
The animation uses @starting-style to animate IN and transition-behavior: allow-discrete to animate OUT — without the second one the panel would vanish instantly on close, because `display` and `overlay` are discrete properties.
Props
<Drawer> props
| Prop | Type | Default | Description |
|---|---|---|---|
openrequired | boolean | — | — |
onCloserequired | () => void | — | — |
labelrequired | string | — | Accessible name for the panel — it has no visible heading of its own. |
closeLabelrequired | string | — | Accessible name for the close button, e.g. "Sulje valikko". |
side | 'left' | 'right' | 'left' | Which edge the panel is attached to. |
className | string | '' | — |
childrenrequired | ReactNode | — | — |
Accessibility
- Native <dialog>, so focus is trapped and Escape closes it.
- `label` names the panel; without it a screen reader announces an unnamed dialog.
Usage
Do
- Put the most important control at the TOP. An expandable list can make the panel taller than a phone, and a button at the bottom then needs scrolling to reach — which is why the navbar’s login button sits above its menu, not below.
- Pass both `label` and `closeLabel`; they are required for a reason.
Don’t
- Don’t render the children while it is closed if they are expensive — this component mounts them only when open.
- Don’t use it on desktop where a Menu would do.