Modal dialog component for focused interactions.
| Name | Type | Default | Description |
|---|---|---|---|
| open | boolean | — | Control dialog open state |
| Property | Token | CSS Variable | Description | |
|---|---|---|---|---|
| Overlay | color.black/40 + backdrop-blur | rgba(0,0,0,0.4) + blur(4px) | Semi-transparent overlay with blur | |
| Background | color.background | var(--background) | Dialog surface | |
| Border | color.border | var(--border) | Dialog border | |
| Shadow | shadow.lg | var(--shadow-lg) | Elevated shadow | |
| Border Radius | borderRadius.lg | var(--radius) | Large corner rounding | |
| Padding | spacing.6 | 1.5rem | Content padding | |
| Animation | animation.duration.normal | 300ms | Open/close duration |
Simple dialog with title and description.
<Dialog>
<DialogTrigger render={<Button />}>
Open Dialog
</DialogTrigger>
<DialogContent>
<DialogHeader>
<DialogTitle>Share document</DialogTitle>
<DialogDescription>
Choose how you'd like to share this document.
</DialogDescription>
</DialogHeader>
<p className="text-fluid-sm pb-6">Select recipients or generate a shareable link.</p>
</DialogContent>
</Dialog>Destructive action confirmation with cancel and confirm buttons.
<Dialog>
<DialogTrigger render={<Button variant="destructive" />}>
Delete Account
</DialogTrigger>
<DialogContent>
<DialogHeader>
<DialogTitle>Are you absolutely sure?</DialogTitle>
<DialogDescription>
This action cannot be undone. This will permanently delete your account and remove
your data from our servers.
</DialogDescription>
</DialogHeader>
<DialogFooter>
<DialogClose render={<Button variant="outline" />}>
Cancel
</DialogClose>
<DialogClose render={<Button variant="destructive" />}>
Delete
</DialogClose>
</DialogFooter>
</DialogContent>
</Dialog>Dialog containing a form with inputs.
<Dialog>
<DialogTrigger render={<Button />}>Edit Profile</DialogTrigger>
<DialogContent>
<DialogHeader>
<DialogTitle>Edit Profile</DialogTitle>
<DialogDescription>
Make changes to your profile here. Save when you're done.
</DialogDescription>
</DialogHeader>
<form onSubmit={(e) => e.preventDefault()} className="space-y-4 py-4">
<FormField label="Name">
<Input defaultValue="John Doe" />
</FormField>
<FormField label="Username" description="This will be your public @handle">
<Input defaultValue="@johndoe" />
</FormField>
<DialogFooter>
<Button type="submit">Save changes</Button>
</DialogFooter>
</form>
</DialogContent>
</Dialog>Dialog state controlled externally via React state.
const [isOpen, setIsOpen] = useState(false);
<Button onClick={() => setIsOpen(true)}>
Open Controlled Dialog
</Button>
<Dialog open={isOpen} onOpenChange={setIsOpen}>
<DialogContent>
<DialogHeader>
<DialogTitle>Controlled Dialog</DialogTitle>
<DialogDescription>
This dialog's state is controlled externally via React state.
</DialogDescription>
</DialogHeader>
<p className="text-fluid-sm">
The open state is managed by the parent component, allowing for
programmatic control.
</p>
<DialogFooter>
<Button onClick={() => setIsOpen(false)}>
Close
</Button>
</DialogFooter>
</DialogContent>
</Dialog>Use max-w-3xl or other width classes for wider content.
<DialogContent className="max-w-3xl">
{/* wider content */}
</DialogContent>Wizard-style dialog with back/next navigation.
<Dialog open={isOpen} onOpenChange={setIsOpen}>
<DialogContent>
<DialogHeader>
<DialogTitle>Setup Wizard</DialogTitle>
<DialogDescription>
Step {currentStep} of 3
</DialogDescription>
</DialogHeader>
{/* Step content */}
<DialogFooterSplit>
<Button variant="outline">Cancel</Button>
<div className="flex gap-2">
{currentStep > 1 && <Button variant="outline">Back</Button>}
<Button>{currentStep < 3 ? 'Next Step' : 'Finish'}</Button>
</div>
</DialogFooterSplit>
</DialogContent>
</Dialog>DialogBody enables scrolling for long content.
<DialogContent className="max-h-[80vh] grid-rows-[auto_1fr_auto]">
<DialogHeader>...</DialogHeader>
<DialogBody className="max-h-96">
{/* Scrollable content */}
</DialogBody>
<DialogFooter>...</DialogFooter>
</DialogContent>