Modal
A blocking dialog with a focus trap, for decisions that can't be deferred.
Use it sparingly
A modal takes the whole page hostage. That's the right trade for a destructive confirmation or a short required form, and the wrong one for anything browsable — a Popover leaves the page behind it usable.
Destructive
Name the consequence in the title and quantify it in the description. "Delete this workspace?" with "all 482 records" is answerable; "Are you sure?" isn't.
Custom body
While an action is in flight
Turn off closeOnEscape and closeOnBackdropClick while confirming, so a stray click can't dismiss the dialog mid-request and leave people unsure whether it went through.
See the code tab.
Props
| Prop | Type | Default | Description |
|---|---|---|---|
| open | boolean | Whether the dialog is shown. Fully controlled. | |
| onClose | () => void | Fires from the ×, Escape, and backdrop click. | |
| title | string | Dialog heading. | |
| description | string | Supporting copy under the title. | |
| variant | 'default' | 'destructive' | 'default' | Destructive adds a warning icon and tints the confirm button. |
| icon | ReactNode | Overrides the destructive variant's TriangleAlert. | |
| children | ReactNode | Custom body between the description and the footer. | |
| confirmLabel / cancelLabel | string | Footer button labels. | |
| onConfirm | () => void | Confirm handler. | |
| onCancel | () => void | onClose | Cancel handler; falls back to onClose. |
| confirmLoading | boolean | false | Puts the confirm button in its loading state. |
| closeOnEscape | boolean | true | Set false to force a decision. |
| closeOnBackdropClick | boolean | true | Set false to force a decision. |