Drawer
Preview: Bottom
Edge-anchored, swipeable panel built on React Aria Sheet (v1.22+). position: bottom (default) | top | left | right | center. Supports snapPoints.
Import
import { Drawer, DrawerTitle, DrawerTrigger } from '@marbleui/ui'Props
<DrawerTitle>
| Prop | Type | Default | Description |
|---|---|---|---|
| children *required | ReactNode | — | |
| description | ReactNode | — |
<DrawerTrigger>alias of SheetTrigger
Re-exported from React Aria SheetTrigger; see its documentation for props.
Accessibility
Keyboard interaction, focus management and ARIA semantics come from the underlying primitives: React Aria Heading · React Aria Sheet · React Aria SheetBackdrop · React Aria SheetContent · React Aria SheetOverlay · React Aria SheetTrigger. Follow the primitive's docs for the full keyboard map.
Usage notes
Swipeable, edge-anchored panel (React Aria Sheet). Bottom sheets on mobile, side panels on desktop.
<DrawerTrigger>
<Button>Filters</Button>
<Drawer snapPoints={['40%', '90%']}>
{({ close }) => (<><DrawerTitle>Filters</DrawerTitle>…<Button onPress={close}>Apply</Button></>)}
</Drawer>
</DrawerTrigger>
position: bottom (default), top, left, right or center.- Always render a
DrawerTitle; it names the dialog. - Users can dismiss by swiping, pressing Escape or tapping the backdrop.
Example source · show· hide
import { Button } from '../button'
import { Checkbox, CheckboxGroup } from '../checkbox'
import { Drawer, DrawerTitle, DrawerTrigger } from './drawer'
export const styles = {
Bottom: () => (
<DrawerTrigger>
<Button variant="outline">Open bottom drawer</Button>
<Drawer>
{({ close }) => (
<div className="flex flex-col pt-2">
<DrawerTitle description="Choose what shows up in your feed.">Filters</DrawerTitle>
<CheckboxGroup aria-label="Filters" defaultValue={['open']}>
<Checkbox value="open">Open issues</Checkbox>
<Checkbox value="mine">Assigned to me</Checkbox>
<Checkbox value="blocked">Blocked</Checkbox>
</CheckboxGroup>
<Button className="mt-6" onPress={close}>Apply</Button>
</div>
)}
</Drawer>
</DrawerTrigger>
),
Right: () => (
<DrawerTrigger>
<Button variant="outline">Open side panel</Button>
<Drawer position="right">
{({ close }) => (
<div className="flex h-full flex-col">
<DrawerTitle description="ACME-142 · In progress">Fix login redirect</DrawerTitle>
<p className="text-sm leading-relaxed text-fg-muted">
After signing in from a deep link, users land on the dashboard instead of the page they asked for.
</p>
<Button className="mt-auto" variant="soft" onPress={close}>Close</Button>
</div>
)}
</Drawer>
</DrawerTrigger>
),
Snap: () => (
<DrawerTrigger>
<Button variant="outline">Open with snap points</Button>
<Drawer snapPoints={['40%', '90%']}>
<div className="pt-2">
<DrawerTitle description="Drag up to expand.">Comments</DrawerTitle>
<div className="flex flex-col gap-3">
{Array.from({ length: 12 }, (_, i) => (
<div key={i} className="rounded-md bg-surface-muted p-3 text-sm text-fg-muted">
Comment {i + 1}: looks good to me, ship it.
</div>
))}
</div>
</div>
</Drawer>
</DrawerTrigger>
),
}Source: packages/ui/src/drawer/drawer.tsx
Catalog
- Category
- overlays
- Priority
- Foundation
- Primitive
- react-aria
- React Aria
- Sheet
- Base UI
- Drawer