Components / Overlays
Drawer Stable A modal panel that slides in from a screen edge for details, filters and secondary tasks.
Drawer keeps the page in context while showing longer content than a Dialog comfortably holds, such as a user’s profile or a filter panel. It shares Dialog’s behaviour: focus trap, scroll lock, Escape to close and focus return. Side panels never exceed the viewport width on phones.
Overview Edit user
tsx Copy
import { Button, Drawer, DrawerBody, DrawerClose, DrawerContent, DrawerDescription, DrawerFooter, DrawerHeader, DrawerTitle, DrawerTrigger, FormField, Input } from '@bindshq/stance-react';
export function Basic() {
return (
<Drawer>
<DrawerTrigger asChild>
<Button variant="outline">Edit user</Button>
</DrawerTrigger>
<DrawerContent>
<DrawerHeader>
<DrawerTitle>Ada Lovelace</DrawerTitle>
<DrawerDescription>Head of Operations · London</DrawerDescription>
</DrawerHeader>
<DrawerBody>
<div style={{ display: 'grid', gap: 16 }}>
<FormField label="Job title">
<Input defaultValue="Head of Operations" />
</FormField>
<FormField label="Direct phone" description="Shown in the signature.">
<Input type="tel" defaultValue="+44 20 7946 0958" />
</FormField>
</div>
</DrawerBody>
<DrawerFooter>
<DrawerClose asChild>
<Button variant="outline">Cancel</Button>
</DrawerClose>
<DrawerClose asChild>
<Button>Save</Button>
</DrawerClose>
</DrawerFooter>
</DrawerContent>
</Drawer>
);
}Light, dark and high contrast Every Stance component is designed and tested in all three appearance modes.
Import tsx Copy
import { Drawer, DrawerTrigger, DrawerContent, DrawerHeader, DrawerTitle, DrawerDescription, DrawerBody, DrawerFooter, DrawerClose } from '@bindshq/stance-react';Examples Slide from any edge. Use left for navigation, right for details.
From left From right From top From bottom
tsx Copy
import { Button, Drawer, DrawerBody, DrawerContent, DrawerHeader, DrawerTitle, DrawerTrigger } from '@bindshq/stance-react';
export function Sides() {
return (
<div style={{ display: 'flex', flexWrap: 'wrap', gap: 12 }}>
{(['left', 'right', 'top', 'bottom'] as const).map((side) => (
<Drawer key={side}>
<DrawerTrigger asChild>
<Button variant="outline">From {side}</Button>
</DrawerTrigger>
<DrawerContent side={side}>
<DrawerHeader>
<DrawerTitle>Drawer from the {side}</DrawerTitle>
</DrawerHeader>
<DrawerBody>Press Escape or click outside to close.</DrawerBody>
</DrawerContent>
</Drawer>
))}
</div>
);
}tsx Copy
import { Button, Drawer, DrawerBody, DrawerContent, DrawerHeader, DrawerTitle, DrawerTrigger } from '@bindshq/stance-react';
export function Sizes() {
return (
<div style={{ display: 'flex', flexWrap: 'wrap', gap: 12 }}>
{(['sm', 'md', 'lg'] as const).map((size) => (
<Drawer key={size}>
<DrawerTrigger asChild>
<Button variant="secondary">Size {size}</Button>
</DrawerTrigger>
<DrawerContent size={size}>
<DrawerHeader>
<DrawerTitle>Size “{size}”</DrawerTitle>
</DrawerHeader>
<DrawerBody>Side drawers never exceed the viewport width.</DrawerBody>
</DrawerContent>
</Drawer>
))}
</div>
);
}API reference DrawerHeader / DrawerBody / DrawerFooter / DrawerDescriptionAccessibility A modal dialog (role="dialog", aria-modal) named by DrawerTitle. Focus is trapped inside and returned to the trigger on close. Respects prefers-reduced-motion: the slide animation is removed. Keyboard Usage guidelines Do Use for detail views that benefit from keeping the list visible behind. Put persistent actions in DrawerFooter. Don’t Use as primary app navigation on desktop; use Sidebar.