Dialog
Modal surface with focus trap, scroll lock and labelling. Escape closes it and focus returns to the opener.
Preview
Live preview
Usage
Examples
Confirmation dialog
<Dialog>
<DialogTrigger asChild>
<Button variant="destructive">Delete project</Button>
</DialogTrigger>
<DialogContent>
<DialogHeader>
<DialogTitle>Delete project?</DialogTitle>
<DialogDescription>This cannot be undone.</DialogDescription>
</DialogHeader>
<DialogFooter>
<Button variant="outline">Cancel</Button>
<Button variant="destructive">Delete</Button>
</DialogFooter>
</DialogContent>
</Dialog>Non-modal, custom close
<Dialog modal={false}>
<DialogTrigger asChild>
<Button variant="outline">Details</Button>
</DialogTrigger>
<DialogContent hideClose>
<DialogHeader>
<DialogTitle>Details</DialogTitle>
<DialogDescription>Inspect the record.</DialogDescription>
</DialogHeader>
<Button variant="ghost" onClick={close}>Close</Button>
</DialogContent>
</Dialog>Reference
Props
| Prop | Type | Default | Description |
|---|---|---|---|
| Dialog modal | boolean | true | Blocks outside interaction, locks scroll and sets aria-modal="true" on the content. |
| Dialog open / onOpenChange | boolean / (open: boolean) => void | — | Controlled open state. |
| DialogContent hideClose | boolean | false | Removes the built-in close button when you render your own. |
| DialogContent className | string | — | Merged last — override width, padding or alignment. |
| DialogTitle (required) | ReactNode | — | Accessible name of the dialog. Always render one. |
| DialogDescription | ReactNode | — | Accessible description; announced after the title. |
| DialogTrigger asChild | boolean | — | Uses your own element as the opener (Radix Slot). |
Accessibility
Accessibility notes
- Content renders role="dialog" with aria-modal="true" (modal dialogs), aria-labelledby (title) and aria-describedby (description).
- DialogTitle is required by design: a dialog without a name is unusable with a screen reader.
- Focus moves into the dialog on open, is trapped while open, and returns to the trigger on close.
- Escape closes the dialog; the built-in close button carries aria-label="Close".
- Modal dialogs lock body scroll; non-modal ones (modal={false}) leave the page scrollable.
- Keep the tab order shallow — the first focusable control should be the primary action.