Components
Dialog
View in FigmaA centered modal dialog — a token-styled wrapper over Base UI's Dialog. Dialog is the state root (open, defaultOpen, onOpenChange, modal); the trigger and close buttons render your element via Base UI's render prop, so a Button stays a full Button — the dialog never mirrors its API.
Install
npx shadcn@latest add @alix/dialogPreview
Usage
<Dialog>
<DialogTrigger render={<Button>New</Button>} />
<DialogContent>
<DialogHeader>
<DialogTitle>Create project</DialogTitle>
<DialogDescription>Give it a name to get started.</DialogDescription>
</DialogHeader>
<Field label="Name">
<Input />
</Field>
<DialogFooter>
<DialogClose render={<Button variant="outline">Cancel</Button>} />
<Button onClick={() => save()}>Create</Button>
</DialogFooter>
</DialogContent>
</Dialog>Examples
01
Destructive confirmation
Use a dialog when a destructive action needs explicit review before it runs.
<Dialog>
<DialogTrigger render={<Button variant="destructive">Remove access</Button>} />
<DialogContent>
<DialogHeader>
<DialogTitle>Remove workspace access?</DialogTitle>
<DialogDescription>
This person will lose access to engagement files and decision notes immediately.
</DialogDescription>
</DialogHeader>
<DialogFooter>
<DialogClose render={<Button variant="outline">Cancel</Button>} />
<DialogClose render={<Button variant="destructive">Remove access</Button>} />
</DialogFooter>
</DialogContent>
</Dialog>02
Engagement form
Field, Input, Select, and Textarea compose inside the modal body while DialogFooter owns action placement.
<Dialog>
<DialogTrigger render={<Button>New engagement</Button>} />
<DialogContent>
<DialogHeader>
<DialogTitle>Create engagement</DialogTitle>
<DialogDescription>Add the basic workspace details before inviting the team.</DialogDescription>
</DialogHeader>
<div className="grid gap-4">
<Field label="Engagement name" required>
<Input placeholder="e.g. Project Atlas" />
</Field>
<Field label="Capability">
<Select
placeholder="Select capability"
items={[
{ value: "turnaround", label: "Turnaround" },
{ value: "transactions", label: "Transactions" },
]}
/>
</Field>
<Field label="Context">
<Textarea rows={3} placeholder="Summarise the client need." />
</Field>
</div>
<DialogFooter>
<DialogClose render={<Button variant="outline">Cancel</Button>} />
<DialogClose render={<Button>Create engagement</Button>} />
</DialogFooter>
</DialogContent>
</Dialog>03
Review summary
A wider dialog can hold a concise decision summary with status badges and a two-action ButtonGroup.
<Dialog>
<DialogTrigger render={<Button variant="outline">Review summary</Button>} />
<DialogContent className="max-w-2xl">
<DialogHeader>
<DialogTitle>Board update summary</DialogTitle>
<DialogDescription>Confirm the key points before the client-facing version is sent.</DialogDescription>
</DialogHeader>
<div className="grid gap-3 text-sm">
<div className="flex items-center justify-between gap-4 border border-border p-3">
<span>Liquidity forecast</span>
<Badge variant="success" dot>Ready</Badge>
</div>
<div className="flex items-center justify-between gap-4 border border-border p-3">
<span>Stakeholder actions</span>
<Badge variant="warning" dot>Needs review</Badge>
</div>
</div>
<DialogFooter>
<ButtonGroup
primaryAction={<DialogClose render={<Button>Send update</Button>} />}
secondaryAction={<DialogClose render={<Button variant="outline">Keep editing</Button>} />}
/>
</DialogFooter>
</DialogContent>
</Dialog>When to use it
Use it for
- Blocking decisions that need focus before the user returns to the page.
- Short create/edit flows with a title, description, fields, and explicit footer actions.
- Destructive confirmations where the consequence needs readable context.
Reach for something else
- Large side panels or filters that should preserve page context — use Drawer instead.
- Anchored helper content tied to one trigger — use Popover instead.
- Transient success or failure messages after an action completes — use Toast instead.
- Overflow command lists — use Menu instead.
Props
| Prop | Type | Default | Description |
|---|---|---|---|
| Dialog | open?, defaultOpen?, onOpenChange?, modal? | — | The state root (Base UI's Dialog.Root). Controls open/close state. |
| DialogTrigger / DialogClose | render: ReactElement | — | Open/close the dialog. They render your element via the render prop, so a Button keeps its full API rather than the dialog re-modelling it. |
| DialogContent | children | — | The portalled scrim + centered popup. Drop a header, body, and footer inside; a top-right close button is included automatically. |
| DialogHeader / DialogTitle / DialogDescription / DialogFooter | children | — | Structural slots: title + description region, and a right-aligned action row that stacks on mobile. |