Dialog
In the appThe modal and the right-hand drawer, one component. Built on the native <dialog>, so focus trapping, Escape and the inert background are free.
@varick/ui/components/dialogAdded 2 Sept 2026
Usage
import {
Dialog, DialogTrigger, DialogContent, DialogHeader, DialogTitle,
DialogDescription, DialogBody, DialogFooter, DialogClose,
} from "@varick/ui/components/dialog";
export function Example() {
return (
<Dialog>
<DialogTrigger variant="primary">Promote to production</DialogTrigger>
<DialogContent>
<DialogHeader>
<DialogTitle>Promote v2.3 to production?</DialogTitle>
<DialogDescription>The current version keeps running until...</DialogDescription>
</DialogHeader>
<DialogBody>...</DialogBody>
<DialogFooter>
<DialogClose />
<Button variant="primary" onClick={promote}>Promote</Button>
</DialogFooter>
</DialogContent>
</Dialog>
);
}Variants
Drawer, for detail panes
<DialogContent variant="drawer">
<DialogHeader>...</DialogHeader>
<DialogBody>...</DialogBody>
<DialogFooter><DialogClose>Close</DialogClose></DialogFooter>
</DialogContent>API reference
Every component also accepts className and the native props of its root element.
| Prop | Type | Default | Description |
|---|---|---|---|
| Dialog.open | boolean | uncontrolled | Controlled open state, with onOpenChange. defaultOpen for uncontrolled. |
| DialogTrigger | Button props + asChild | Renders a Button, or decorates the child. | |
| DialogContent.variant | 'modal' | 'drawer' | 'modal' | Centred at 480px, or a 500px right-hand pane. |
| DialogContent.showClose | boolean | true | The X in the top corner. |
| DialogClose.children | ReactNode | 'Cancel' | An outline Button that closes. |
Accessibility
- A native <dialog> opened with showModal(): focus is trapped, the page behind is inert, Escape closes.
- aria-labelledby and aria-describedby point at DialogTitle and DialogDescription. Always include a title.
- Clicking the backdrop closes; content clicks do not bubble to it.
Styles
The CSS as it appears in the app. The live component above is the same values as Tailwind classes.
.modal-backdrop { position: fixed; inset: 0; background: rgba(17,17,17,0.32); }
.drawer {
width: 500px;
max-width: 100%;
background: #FFFFFF;
border-radius: 8px;
box-shadow: 0 24px 64px rgba(0,0,0,0.18);
display: flex;
flex-direction: column;
overflow: hidden;
transform: translateX(16px) scale(0.99);
opacity: 0;
transition: transform 260ms var(--ease-out), opacity 220ms var(--ease-out);
}
.drawer-head { padding: 20px 24px; border-bottom: 1px solid var(--hairline-soft); }
.drawer-title { font-size: 16px; font-weight: 500; letter-spacing: -0.01em; }
.drawer-body { flex: 1; overflow-y: auto; padding: 20px 24px 24px; }
.drawer-foot { display: flex; justify-content: space-between; padding: 16px 24px; border-top: 1px solid var(--hairline-soft); }
.modal-head { padding: 16px 20px; border-bottom: 1px solid var(--hairline-soft); }
.modal-title { font-size: 15px; font-weight: 500; }