A React dialog with a Liquid Glass surface and a custom action area.
Dialog is a general-purpose modal. It renders the portal, backdrop, centered popup, title, description, optional body, and a custom action area internally.
Unlike AlertDialog, which always blocks backdrop dismissal, Dialog can be dismissed by pressing the backdrop or Escape, and footer can render any number and any kind of action buttons.
The component is typically used in controlled mode: open controls visibility and the page renders its own trigger button. Put your buttons in footer and close the dialog with setOpen(false).
footer is a regular React node, so it can hold two, three, or more buttons, or a mix of other controls. Buttons do not close the dialog automatically; update open yourself as the example does.
No release published.
disablePointerDismissal prevents the backdrop from closing the dialog while Escape still works. Use it for flows that may contain unsaved work.
Dialog renders a modal dialog named by title and described by description. Focus moves into the popup, stays trapped while it is open, and returns to the trigger when it closes.
Escape and backdrop clicks close it by default. disablePointerDismissal stops backdrop clicks only; Escape still closes the dialog. Provide a visible close action in footer. modal={false} relaxes focus trapping and scroll locking. See the accessibility guide for overlay focus rules.
| Prop | Type | Default | Description |
|---|---|---|---|
title | ReactNode | — | Dialog heading. Required. |
description | ReactNode | — | Supporting copy under the title. |
children | ReactNode | — | Body content between the description and the action area. |
footer | ReactNode | — | Bottom action area that can hold any number of controls. |
open | boolean | — | Controlled open state. |
defaultOpen | boolean | false | Initial open state when uncontrolled. |
onOpenChange | (open: boolean, details) => void | — | Called when the dialog opens or closes. |
onOpenChangeComplete | (open: boolean) => void | — | Called after the open or close animation finishes. |
modal | boolean | "trap-focus" | true | Controls focus trapping and page scroll locking. |
disablePointerDismissal | boolean | false | Prevents the backdrop from closing the dialog. |
actionsRef | RefObject<Actions | null> | — | Imperative close and unmount actions. |
handle | DialogHandle | — | Associates the dialog with external triggers. |
triggerId | string | null | — | ID of the trigger associated with the dialog. |
defaultTriggerId | string | null | — | ID of the trigger used for an initially open dialog. |
className | string | — | Tailwind classes merged into the popup. |
style | CSSProperties | — | Inline styles merged into the same element as className. |
ui | { backdrop?: ClassValue; viewport?: ClassValue; popup?: ClassValue; glass?: ClassValue; overlay?: ClassValue; content?: ClassValue; title?: ClassValue; description?: ClassValue; body?: ClassValue; footer?: ClassValue } | — | Tailwind classes for internal slots, keyed by data-slot. |
| Attribute | Description |
|---|---|
data-open | Present when the dialog is open. |
data-closed | Present when the dialog is closed. |
data-starting-style | Present when the dialog begins animating in. |
data-ending-style | Present when the dialog is animating out. |
data-nested | Present when the dialog is nested within another dialog. |
data-nested-dialog-open | Present when another dialog is open inside this one. |
data-slot | Marks internal parts (backdrop, viewport, popup, glass, overlay, content, title, description, body, footer) for styling. |
The component uses the shared glass material. Tune shared --ui-glass-* tokens on a parent, use className for layout, and use ui for internal slots keyed by data-slot. Component-specific values live in src/theme/dialog.ts. See the theming guide for token layers and presets.