Dialog
A window overlaid on either the primary window or another dialog window, rendering the content underneath inert.
Made by imskyleenInstallation
When to use
Use this decision tree to determine when to use the Dialog component:
Usage
<Dialog>
<DialogTrigger>Open Dialog</DialogTrigger>
<DialogContent>
<DialogHeader>
<DialogTitle>Title</DialogTitle>
<DialogDescription>Description</DialogDescription>
</DialogHeader>
<p>Dialog Content</p>
<DialogFooter>
<button>Close</button>
</DialogFooter>
</DialogContent>
</Dialog>Props
Examples
Default
Delete
No Header
Skip the header when the dialog body stands on its own — the close button stays at the top-right and the top border is omitted since there's nothing to separate from.
No Footer
Omit the footer when the dialog is informational and doesn't require explicit actions beyond dismissing.
Scrolling content
DialogContent caps at max-h-[85vh] and DialogBody is the scrollable region — long content gets a pinned header/footer with an internal scrollbar for free.
No Header or Footer
Use body-only dialogs sparingly — without a visible header the dialog still needs an accessible name, so render a DialogTitle with className="sr-only" for screen readers. Add right-padding to the body so content clears the absolute-positioned close button.
Footer with helper text
When the footer pairs metadata or status text (e.g. "Changes are saved automatically") with a single dismiss action, use justify="between" so the text sits on the left and the button on the right. The footer centers items vertically by default, so the text baseline aligns cleanly with the button.
Animate UI Props
DialogContent
Prop
Type
Keyboard interactions
| Key | Action |
|---|---|
Enter / Space on DialogTrigger | Opens the dialog and moves focus to the first focusable element inside DialogContent. |
Tab / Shift+Tab | Cycles focus within the dialog — focus is trapped while open. |
Escape | Closes the dialog and restores focus to the trigger. |
Click outside DialogContent | Closes the dialog (modal scrim dismiss). |
Accessibility
- Render a
DialogTitle(or a visually-hidden one) — Base UI enforces this with a development warning. The dialog is labelled viaaria-labelledbypointing at the title. - Add a
DialogDescriptionwhen the dialog's purpose isn't obvious from the title; it is wired up viaaria-describedby. - Focus is trapped inside the popup while open and returned to the trigger on close. Background content is marked
aria-hiddenand made inert so assistive tech doesn't reach it. onOpenChangeis the Radix-style single-argument(open: boolean) => void; the compat layer narrows Base UI's(open, details)signature so existing handlers keep working.
Controlled vs uncontrolled
Uncontrolled — let the dialog own open state, react via onOpenChange:
<Dialog onOpenChange={(open) => console.log('open:', open)}>
<DialogTrigger>Open</DialogTrigger>
<DialogContent>{/* ... */}</DialogContent>
</Dialog>Controlled — drive open from parent state, e.g. to open the dialog from a menu item or remote action:
const [open, setOpen] = useState(false);
<Dialog open={open} onOpenChange={setOpen}>
<DialogTrigger>Open</DialogTrigger>
<DialogContent>
<DialogFooter>
<Button onClick={() => setOpen(false)}>Done</Button>
</DialogFooter>
</DialogContent>
</Dialog>Credits
- We use Base UI for the dialog component.
- We take our inspiration from Shadcn UI for the dialog style.
- We use Animate UI from imskyleen for all the animations.
Recent changes
- patchv1.2.0Pin shipped dependency floors to the version we develop against. Registry items now declare ranges like `^5.1.9` (the actual installed version) instead of collapsing to `^5.0.0`, so consumers start on the known-tested b…#133
- minorv1.1.0Theme docs refresh, readability pass on semantic foregrounds, and consumer-facing Base UI regression fixes.#121
- minorv1.1.0Bulk install experience and Dialog polish.#119
- minorv1.0.0Post-Base-UI polish. Public API unchanged.#116
- majorv1.0.0Migrate every Radix-based primitive to `@base-ui/react@^1.4.0` (Base UI).#114