A modal panel that slides in from the left, right, or bottom, with swipe dismissal and accessible focus management.
Delete workspace?
12 projects and 3,400 files will be permanently removed. This can't be undone.
---import { Button } from '@bejamas/registry/ui/button';import { Drawer, DrawerBody, DrawerContent, DrawerDescription, DrawerFooter, DrawerHeader, DrawerTitle } from '@bejamas/registry/ui/drawer';---
<Drawer side="right"> <Button data-slot="drawer-trigger">Open drawer</Button> <DrawerContent> <DrawerHeader><DrawerTitle>Delete workspace?</DrawerTitle><DrawerDescription>12 projects and 3,400 files will be permanently removed. This can't be undone.</DrawerDescription></DrawerHeader> <DrawerBody class="space-y-2"> <div class="flex h-[300px] items-center justify-center rounded-lg bg-muted text-muted-foreground">Slot area</div> <div class="flex h-[300px] items-center justify-center rounded-lg bg-muted text-muted-foreground">Slot area</div> </DrawerBody> <DrawerFooter><Button data-slot="drawer-close" size="sm">Delete workspace</Button><Button data-slot="drawer-close" variant="secondary" size="sm">Cancel</Button></DrawerFooter> </DrawerContent></Drawer>Installation
Section titled “Installation”bunx bejamas add drawernpx bejamas add drawerpnpm dlx bejamas add draweryarn dlx bejamas add drawer---import { Drawer, DrawerContent, DrawerHeader, DrawerTitle, DrawerDescription, DrawerBody, DrawerFooter } from '@bejamas/registry/ui/drawer';import { Button } from '@bejamas/registry/ui/button';---<Drawer side="right"> <Button data-slot="drawer-trigger">Open drawer</Button> <DrawerContent> <DrawerHeader><DrawerTitle>Drawer title</DrawerTitle><DrawerDescription>Drawer description.</DrawerDescription></DrawerHeader> <DrawerBody>Drawer content</DrawerBody> <DrawerFooter><Button data-slot="drawer-close" variant="secondary">Close</Button></DrawerFooter> </DrawerContent></Drawer>| Prop | Type | Default |
|---|---|---|
side |
"left" | "right" | "bottom" |
"right" |
defaultOpen |
boolean |
false |
modal |
boolean | "trap-focus" |
true |
disablePointerDismissal |
boolean |
false |
closeOnEscape |
boolean |
true |
class |
string |
"" |
Examples
Section titled “Examples”Right drawer
Section titled “Right drawer”Delete workspace?
12 projects and 3,400 files will be permanently removed. This can't be undone.
---import { Button } from '@bejamas/registry/ui/button';import { Drawer, DrawerBody, DrawerContent, DrawerDescription, DrawerFooter, DrawerHeader, DrawerTitle } from '@bejamas/registry/ui/drawer';---
<Drawer side="right"> <Button data-slot="drawer-trigger">Open right drawer</Button> <DrawerContent> <DrawerHeader><DrawerTitle>Delete workspace?</DrawerTitle><DrawerDescription>12 projects and 3,400 files will be permanently removed. This can't be undone.</DrawerDescription></DrawerHeader> <DrawerBody class="space-y-2"> <div class="flex h-[300px] items-center justify-center rounded-lg bg-muted text-muted-foreground">Slot area</div> <div class="flex h-[300px] items-center justify-center rounded-lg bg-muted text-muted-foreground">Slot area</div> </DrawerBody> <DrawerFooter><Button data-slot="drawer-close" size="sm">Delete workspace</Button><Button data-slot="drawer-close" variant="secondary" size="sm">Cancel</Button></DrawerFooter> </DrawerContent></Drawer>Left drawer
Section titled “Left drawer”Delete workspace?
12 projects and 3,400 files will be permanently removed. This can't be undone.
---import { Button } from '@bejamas/registry/ui/button';import { Drawer, DrawerBody, DrawerContent, DrawerDescription, DrawerFooter, DrawerHeader, DrawerTitle } from '@bejamas/registry/ui/drawer';---
<Drawer side="left"> <Button data-slot="drawer-trigger">Open left drawer</Button> <DrawerContent> <DrawerHeader><DrawerTitle>Delete workspace?</DrawerTitle><DrawerDescription>12 projects and 3,400 files will be permanently removed. This can't be undone.</DrawerDescription></DrawerHeader> <DrawerBody class="space-y-2"> <div class="flex h-[300px] items-center justify-center rounded-lg bg-muted text-muted-foreground">Slot area</div> <div class="flex h-[300px] items-center justify-center rounded-lg bg-muted text-muted-foreground">Slot area</div> </DrawerBody> <DrawerFooter><Button data-slot="drawer-close" size="sm">Delete workspace</Button><Button data-slot="drawer-close" variant="secondary" size="sm">Cancel</Button></DrawerFooter> </DrawerContent></Drawer>Bottom drawer
Section titled “Bottom drawer”Delete workspace?
12 projects and 3,400 files will be permanently removed. This can't be undone.
---import { Button } from '@bejamas/registry/ui/button';import { Drawer, DrawerBody, DrawerContent, DrawerDescription, DrawerFooter, DrawerHeader, DrawerTitle } from '@bejamas/registry/ui/drawer';---
<Drawer side="bottom"> <Button data-slot="drawer-trigger">Open bottom drawer</Button> <DrawerContent> <DrawerHeader><DrawerTitle>Delete workspace?</DrawerTitle><DrawerDescription>12 projects and 3,400 files will be permanently removed. This can't be undone.</DrawerDescription></DrawerHeader> <DrawerBody class="flex h-[300px] items-center justify-center rounded-lg bg-muted text-muted-foreground">Slot area</DrawerBody> <DrawerFooter><Button data-slot="drawer-close" size="sm">Delete workspace</Button><Button data-slot="drawer-close" variant="secondary" size="sm">Cancel</Button></DrawerFooter> </DrawerContent></Drawer>API Reference
Section titled “API Reference”See @data-slot documentation for more info.
Events
Section titled “Events”The drawer emits custom events on its root element:
| Event | Detail | Description |
|---|---|---|
drawer:beforechange |
{ open, reason, trigger, payload, originalEvent? } |
Fired before the open state changes; cancel with event.preventDefault() or event.detail.cancel() |
drawer:change |
{ open, reason, trigger, payload, originalEvent? } |
Fired after the open state changes |
drawer:change-complete |
{ open: boolean } |
Fired after the opening or closing transition finishes |
<Drawer id="my-drawer"> <Button data-slot="drawer-trigger">Open drawer</Button> <DrawerContent> <DrawerHeader><DrawerTitle>Drawer title</DrawerTitle></DrawerHeader> <DrawerBody>Drawer content</DrawerBody> <DrawerFooter><Button data-slot="drawer-close">Close</Button></DrawerFooter> </DrawerContent></Drawer>const drawer = document.getElementById('my-drawer');
drawer.addEventListener('drawer:change', (event) => { console.log('Is open:', event.detail.open);});Data Attributes
Section titled “Data Attributes”The drawer exposes these attributes for styling and state queries:
| Attribute | Element | Description |
|---|---|---|
data-state |
drawer, portal, backdrop, viewport, popup | Current state (open or closed) |
data-swipe-direction |
drawer, portal, backdrop, viewport, popup | Dismissal direction (left, right, or down) |
data-popup-open |
active trigger | Present while its drawer is open |
data-swiping |
backdrop, viewport, popup | Present during a swipe gesture |
data-starting-style, data-ending-style |
backdrop, popup | Present during entry or exit transitions |