01
Overview
Edge-anchored overlay panel for supplementary content without leaving the current page. The placement prop picks the edge: left, right (default), or bottom for mobile-style bottom sheets.
Choosing this component
- Showing detail or edit forms alongside a list or table where the user needs to stay in context.
- Navigation trees, filter panels, or settings that the user may want to keep open while interacting with the page.
- Secondary workflows that complement the current view rather than replacing it.
- Mobile-first surfaces that should slide up from the bottom of the viewport — use
placement="bottom", optionally withdragHandleVisible.
Choosing something else
- Full-screen workflows that require the user's full attention — use a
Modalor navigate to a new page. - Brief contextual explanations or single-action prompts — use a
Popoverinstead.
Related components
Modal— blocking full-attention overlay when the user cannot continue without acting.Sidebar— persistent side panel that is always visible (not overlaid).
Usage
02
When to use
Use when
- Showing supplementary navigation, filters, or settings that should slide in from a page edge.
- Presenting long-form content that benefits from a side panel without leaving the current view.
- Presenting a focused task or set of actions that slides up from the bottom of the viewport on touch surfaces — use `placement="bottom"`.
Avoid when
- Interrupting the user for a focused decision — use modal so the surface is centered and task-scoped.
- Anchoring a small surface to a trigger — use popover instead.
03
Examples
Basic drawer
An edge-anchored slide-in panel with controls for placement, size, and triggerRef.
Bottom sheet
A bottom-placed drawer with a drag handle and enough content to scroll.
Overflowing drawer
A side drawer with a scrollable body.
04
Props
| Name | Type | Default | Description |
|---|---|---|---|
open bindable | boolean | false | Whether the drawer is open. Bindable via bind:open. |
placement | 'left' | 'right' | 'bottom' | 'right' | Edge the drawer slides in from. |
size | 'sm' | 'md' | 'lg' | 'xl' | 'md' | Drawer width token for left/right placements.
Ignored for placement="bottom", which always spans the full viewport
width and caps its height at 90dvh. |
title required | text | Accessible name for the drawer. Required for screen-reader labelling.
Rendered as a visible <h2> in the default header. When a custom
header snippet is provided without ariaLabelledby, this text is
rendered in a visually-hidden <h2> as the accessible name fallback. | |
triggerRef | HTMLElement | null | null | Optional reference to the element that opened the drawer. When supplied, focus returns to this element on close. When omitted, focus restores to the element that held focus before the drawer opened. |
ariaLabelledby | text | Optional id of an element that names the drawer. When supplied, drawer
wires aria-labelledby to this id and renders no internal heading.
Use this when a custom header snippet has its own visible heading —
supply ariaLabelledby pointing to that heading's id so the
visible and accessible names stay in sync. | |
dragHandleVisible | boolean | false | When true and placement="bottom", render a decorative drag handle
above the header. Swipe-to-close gesture is a stretch goal not
implemented in MVP — the handle is purely a visual affordance.
Ignored for left/right placements.
Named dragHandleVisible (not draggable) to avoid colliding with the
native HTML draggable attribute on the underlying <dialog>. |
header | snippet | Custom header. Falls back to a default header that renders title. | |
children required | snippet | Drawer body content. Required. | |
footer | snippet | Optional footer (e.g. action buttons). |