Dialog
Overview
Dialogs present focused, interruptive content above the main interface, typically requiring acknowledgment or a decision before continuing.
<Dialog.Root>
<Dialog.Trigger render={<Button label="Open dialog" priority="primary" />} />
<Dialog.Content>
<Dialog.Header
title="Here's a sample dialog"
description="It can include an optional description that provides a bit more context for the user. Isn't that nice?"
/>
<Dialog.Actions>
<Button label="Confirm" priority="primary" />
<Dialog.Close render={<Button label="Cancel" />} />
</Dialog.Actions>
</Dialog.Content>
</Dialog.Root>Usage Guidelines
- Use for important interruptions: Use a dialog when users need to stop and make a decision before continuing, such as confirming a destructive action or completing a short focused task. Avoid it for information that can stay in the page flow.
- Keep content focused: Limit dialog content to the context people need to make the decision or complete the task. Long forms, dense layouts, or content that requires extended browsing usually fit better in the page itself.
- Make actions clear: Include a clear primary action and a clear way to dismiss the dialog. Use action labels that describe the outcome, such as "Delete project" or "Save changes," rather than vague labels like "OK."
API Reference
Dialog.Root
Controls dialog state and provides context for all nested dialog parts.
| Prop | Type | Default |
|---|---|---|
children | ReactNode | ((actions: { close: () => void }) => ReactNode) | - |
open | boolean | - |
defaultOpen | boolean | - |
onOpenChange | (open: boolean) => void | - |
Dialog.Trigger
Interactive element that opens the dialog when activated.
| Prop | Type | Default |
|---|---|---|
render | ReactElement | - |
disabled | boolean | false |
children | ReactNode | - |
Dialog.Content
Portal-rendered container for the dialog surface, backdrop, and viewport positioning.
| Prop | Type | Default |
|---|---|---|
children | ReactNode | - |
className | string | - |
initialFocus | RefObject<HTMLElement> | (() => HTMLElement | null) | - |
finalFocus | RefObject<HTMLElement> | (() => HTMLElement | null) | - |
Dialog.Header
Structured heading block that renders the dialog title and optional description.
| Prop | Type | Default |
|---|---|---|
title | string | - |
description | string | - |
Dialog.Body
Main content region for dialog copy, fields, or custom layout.
| Prop | Type | Default |
|---|---|---|
children | ReactNode | - |
Dialog.Actions
Action row for primary and secondary controls, typically aligned to the end.
| Prop | Type | Default |
|---|---|---|
children | ReactNode | - |
Dialog.Close
Control that closes the dialog, often used for cancel or dismiss actions.
| Prop | Type | Default |
|---|---|---|
render | ReactElement | - |
children | ReactNode | - |
disabled | boolean | false |
Examples
Confirmation
Use a dialog to confirm an action that interrupts the current flow, especially when the result is destructive or difficult to undo.
<Dialog.Root>
{({ close }) => (
<>
<Dialog.Trigger render={<Button label="Delete workspace" />} />
<Dialog.Content>
<Dialog.Header
title="Delete workspace?"
description="This removes all projects, drafts, and team access for this workspace. This action cannot be undone."
/>
<Dialog.Actions>
<Button label="Delete workspace" priority="primary" onClick={() => close()} />
<Dialog.Close render={<Button label="Keep workspace" />} />
</Dialog.Actions>
</Dialog.Content>
</>
)}
</Dialog.Root>Short tasks
Dialogs can hold short, focused tasks such as renaming an item or updating a single setting. Keep the content brief so the task stays easy to complete in place.
<Dialog.Root>
{({ close }) => (
<>
<Dialog.Trigger render={<Button label="Rename workspace" priority="primary" />} />
<Dialog.Content>
<Dialog.Header title="Update project" description="Changes will be reflected upon publish" />
<Dialog.Body>
<Stack gap={5}>
<Field label="Title">
<Input defaultValue="My Example Project" width="fluid" />
</Field>
<Field label="Description">
<Input defaultValue="It's really cool" width="fluid" />
</Field>
</Stack>
</Dialog.Body>
<Dialog.Actions>
<Button label="Save changes" priority="primary" onClick={() => close()} />
<Dialog.Close render={<Button label="Cancel" />} />
</Dialog.Actions>
</Dialog.Content>
</>
)}
</Dialog.Root>Controlled state
Use the controlled API when dialog visibility depends on application state instead of on a user-initiated trigger, such as part of a larger workflow.
const [open, setOpen] = useState(false);
<Dialog.Root open={open} onOpenChange={setOpen}>
{({ close }) => (
<>
<Button label="Open controlled dialog" priority="primary" onClick={() => setOpen(true)} />
<Dialog.Content>
<Dialog.Header
title="Publish changes?"
description="This dialog is controlled by external state instead of relying only on the trigger."
/>
<Dialog.Actions>
<Button label="Publish" priority="primary" onClick={() => close()} />
<Dialog.Close render={<Button label="Cancel" />} />
</Dialog.Actions>
</Dialog.Content>
</>
)}
</Dialog.Root>