Components
A window overlaid on the primary window, rendering the content underneath inert.
Playground
asChild; the top-corner close button ships by default.import {
Dialog,
DialogClose,
DialogContent,
DialogDescription,
DialogFooter,
DialogHeader,
DialogTitle,
DialogTrigger,
} from "@workspace/ui/components/dialog"
<Dialog>
<DialogTrigger asChild>
<Button variant="outline">Open dialog</Button>
</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 asChild>
<Button variant="outline">Cancel</Button>
</DialogClose>
<Button>Continue</Button>
</DialogFooter>
</DialogContent>
</Dialog>gap-6 — no extra wrappers needed.<Dialog>
<DialogTrigger asChild>
<Button variant="outline">Edit profile</Button>
</DialogTrigger>
<DialogContent className="sm:max-w-sm">
<DialogHeader>
<DialogTitle>Edit profile</DialogTitle>
<DialogDescription>
Make changes to your profile here. Click save when you're done.
</DialogDescription>
</DialogHeader>
<FieldGroup>
<Field>
<FieldLabel htmlFor="profile-name">Name</FieldLabel>
<Input id="profile-name" defaultValue="Pedro Duarte" />
</Field>
<Field>
<FieldLabel htmlFor="profile-username">Username</FieldLabel>
<Input id="profile-username" defaultValue="@peduarte" />
</Field>
</FieldGroup>
<DialogFooter>
<DialogClose asChild>
<Button variant="outline">Cancel</Button>
</DialogClose>
<Button type="submit">Save changes</Button>
</DialogFooter>
</DialogContent>
</Dialog>sm:justify-start for a share-link pattern.<Dialog>
<DialogTrigger asChild>
<Button variant="outline">Share</Button>
</DialogTrigger>
<DialogContent className="sm:max-w-md">
<DialogHeader>
<DialogTitle>Share link</DialogTitle>
<DialogDescription>
Anyone who has this link will be able to view this.
</DialogDescription>
</DialogHeader>
<div className="grid gap-2">
<Label htmlFor="share-link" className="sr-only">
Link
</Label>
<Input
id="share-link"
defaultValue="https://westy.la/design-system"
readOnly
/>
</div>
<DialogFooter className="sm:justify-start">
<DialogClose asChild>
<Button type="button">Close</Button>
</DialogClose>
</DialogFooter>
</DialogContent>
</Dialog>showCloseButton on DialogContent hides the top-corner control; the same prop on DialogFooter renders a ready-made outline Close button instead. Keep at least one visible way out — Escape and overlay clicks still close either way.<Dialog>
<DialogTrigger asChild>
<Button variant="outline">No close button</Button>
</DialogTrigger>
<DialogContent showCloseButton={false}>
<DialogHeader>
<DialogTitle>No close button</DialogTitle>
<DialogDescription>
This dialog hides the top-corner close control and relies on the
footer instead.
</DialogDescription>
</DialogHeader>
<DialogFooter showCloseButton />
</DialogContent>
</Dialog>max-h-[50vh] overflow-y-auto and the header and footer stay pinned while the body scrolls. The negative -mx-6 px-6 lets the scrollbar sit at the dialog edge without clipping the padding.<Dialog>
<DialogTrigger asChild>
<Button variant="outline">Terms of service</Button>
</DialogTrigger>
<DialogContent>
<DialogHeader>
<DialogTitle>Terms of service</DialogTitle>
<DialogDescription>
Read the terms below — the footer stays visible while you scroll.
</DialogDescription>
</DialogHeader>
<div className="-mx-6 max-h-[50vh] overflow-y-auto px-6">
{Array.from({ length: 10 }).map((_, index) => (
<p key={index} className="mb-4 leading-normal">
Lorem ipsum dolor sit amet, consectetur adipiscing elit...
</p>
))}
</div>
<DialogFooter>
<DialogClose asChild>
<Button variant="outline">Close</Button>
</DialogClose>
<Button>Accept</Button>
</DialogFooter>
</DialogContent>
</Dialog>start-1/2, end-4), so passing dir="rtl" mirrors the close button and footer without extra classes.<Dialog>
<DialogTrigger asChild>
<Button variant="outline">فتح النافذة</Button>
</DialogTrigger>
<DialogContent dir="rtl" className="sm:max-w-sm">
<DialogHeader>
<DialogTitle>تعديل الملف الشخصي</DialogTitle>
<DialogDescription>
قم بإجراء تغييرات على ملفك الشخصي هنا. انقر على حفظ عند الانتهاء.
</DialogDescription>
</DialogHeader>
<DialogFooter>
<DialogClose asChild>
<Button variant="outline">إلغاء</Button>
</DialogClose>
<Button>حفظ</Button>
</DialogFooter>
</DialogContent>
</Dialog>aria-labelledby and is required — if the design hides it, keep it in the tree with sr-only. DialogDescription wires up aria-describedby, and the built-in close button carries a screen-reader-only label.<DialogContent>
<DialogHeader>
<DialogTitle className="sr-only">Search</DialogTitle>
<DialogDescription className="sr-only">
Search the documentation
</DialogDescription>
</DialogHeader>
{/* visually title-less content */}
</DialogContent>asChild to keep your own markup), DialogPortal and DialogOverlay handled automatically by DialogContent, plus the DialogHeader / DialogTitle / DialogDescription / DialogFooter layout parts. All accept their underlying element props.| Component | Prop | Default |
|---|---|---|
| Dialog | open?: boolean, onOpenChange?: (open: boolean) => void | — |
| Dialog | modal?: boolean | true |
| DialogContent | showCloseButton?: boolean | true |
| DialogFooter | showCloseButton?: boolean | false |
| DialogTrigger / DialogClose | asChild?: boolean | false |
<Dialog data-slot="dialog" /> <DialogTrigger data-slot="dialog-trigger" /> <DialogContent data-slot="dialog-content" data-open data-closed /> <DialogOverlay data-slot="dialog-overlay" /> <DialogHeader data-slot="dialog-header" /> <DialogTitle data-slot="dialog-title" /> <DialogDescription data-slot="dialog-description" /> <DialogFooter data-slot="dialog-footer" /> <DialogClose data-slot="dialog-close" />
Tokens used
9 design tokens consumed by the Dialog component.
--popover
Popover
--popover-foreground
Popover Foreground
--foreground
Foreground
--muted-foreground
Muted Foreground
--font-heading
GT Alpina Condensed
--text-sm
Text Small (14px)
--font-weight-medium
Font weight Medium (500)
--radius-xl
Radius 1.4× (14px)
--spacing
Spacing unit (4px)