Overlays
Dialog
A modal window for a focused task. Focus is trapped and returned on close.
Live example
Usage
<Dialog
open={open}
onOpenChange={setOpen}
title="New booking"
footer={<Button variant="primary" type="submit" form="booking">Save</Button>}
>
<form id="booking">...</form>
</Dialog>Props
| Prop | Type | Default | Description |
|---|---|---|---|
open | boolean | none | Whether the dialog is shown. |
onOpenChange | (open: boolean) => void | none | Called with false on Escape, backdrop click or close. |
title | ReactNode | none | Heading that names the dialog. |
description? | ReactNode | none | Short text that describes the dialog. |
footer? | ReactNode | none | Actions. Put the primary action last. |
initialFocus? | RefObject<HTMLElement> | none | Element to focus on open. Defaults to the first field. |
role? | 'dialog' | 'alertdialog' | 'dialog' | alertdialog for confirmations; it ignores backdrop clicks. |
size? | 'sm' | 'md' | 'lg' | 'md' | Maximum width. |
Do and don't
Do
- Use for short, focused tasks such as creating a record.
- Give every dialog a clear title and a visible way to close.
Don't
- Open a dialog from a dialog.
- Use a dialog for content people need to compare with the page behind.
Accessibility
- role dialog with aria-modal, named by the title and described by the description.
- The rest of the page gets the inert attribute, so screen reader virtual cursors cannot leave the dialog.
- Focus moves to the first field on open and returns to the trigger on close. Body scroll is locked.
Keyboard
| Keys | Action |
|---|---|
| Tab, Shift + Tab | Cycle through controls inside the dialog only |
| Escape | Closes the dialog |