Skip to main content
Use Dialog for forms, details, and other tasks that open above the page. It manages focus, keyboard dismissal, outside clicks, and scrolling. Use AlertDialog when the user must explicitly respond to a decision.

Anatomy

Uncontrolled state

Root owns visibility by default. Set defaultOpen for its initial state. Triggers, close controls, Escape, and outside clicks update that state.

Controlled state

Pass open and onOpenChange when the application owns visibility. The callback receives the requested state and event details. Update state to accept a change, or call eventDetails.cancel() to reject it.
For an asynchronous form, keep the dialog open while submitting. Close it after success and display failures inside the dialog.

Composition

Trigger and Close accept render to compose with Button, as shown above. Custom wrappers must forward supplied props and refs. Layout parts also support render, native attributes, refs, styles, and class names. Popup, Title, and Description accept state-aware class names and styles. Nest another Dialog.Root inside a popup to open a second dialog. Closing the nested dialog returns focus to its trigger in the parent. To open one dialog from triggers outside Root, create a handle once with Dialog.createHandle() and pass it to handle on both Root and each Trigger. Trigger payload values are available in Root’s render function. Title uses Heading and defaults to an h2 with large type, primary text color, centered alignment, and spacing-4 below it. Use level to change the heading level independently of size, or color to change its text color. Native className, style, refs, and render are forwarded to the heading. Keep a heading element when using render.

Focus, scrolling, and dismissal

Root.modal controls the interaction boundary: Set Popup.backdrop={false} when outside content should remain visible and interactive. Set Popup.initialFocus or Popup.finalFocus to a ref or callback to choose focus targets; false disables that automatic focus move. Root.disablePointerDismissal prevents outside clicks from requesting closure. To prevent Escape dismissal, cancel the escape-key change in onOpenChange. Always provide a visible way to close a modal dialog.

Sizes and portals

Popup.size accepts sm, md, lg, xl, and fullscreen, and defaults to md. Long content scrolls within the popup. Width is constrained to the viewport. Portals use the nearest theme container by default and preserve text direction. Set container to an element or ref to choose another destination; null defers mounting until a destination is available. keepMounted retains content and form state while closed. Use backdrop props to customize the backdrop, and viewportProps for native attributes, styles, or render composition on the surrounding viewport. These props let application layout containers host a dialog while keeping the popup’s semantics.

Props

Dialog.Root

RefObject<DialogRootActions | null>
A ref to imperative actions.
  • unmount: Manually unmounts the dialog. Call this after any externally controlled closing animation finishes.
  • close: Closes the dialog imperatively when called.
ReactNode | PayloadChildRenderFunction<Payload>
The content of the dialog. This can be a regular React node or a render function that receives the payload of the active trigger.
boolean
default:"false"
Whether the dialog is initially open.To render a controlled dialog, use the open prop instead.
string | null
ID of the trigger that the dialog is associated with. This is useful in conjunction with the defaultOpen prop to create an initially open dialog.
boolean
default:"false"
Whether to prevent the dialog from closing on outside presses. For non-modal dialogs, this also prevents the dialog from closing when focus moves outside of it.
DialogHandle<Payload>
A handle to associate the dialog with a trigger. If specified, allows external triggers to control the dialog’s open state. Can be created with the Dialog.createHandle() method.
boolean | "trap-focus"
default:"true"
Determines if the dialog enters a modal state when open.
  • true: user interaction is limited to just the dialog: focus is trapped, document page scroll is locked, and pointer interactions on outside elements are disabled.
  • false: user interaction with the rest of the document is allowed.
  • 'trap-focus': focus is trapped inside the dialog, but document page scroll is not locked and pointer interactions outside of it remain enabled.
When modal is true or 'trap-focus', render <Dialog.Close> inside <Dialog.Popup> so touch screen readers can escape the popup.
((open: boolean, eventDetails: DialogRootChangeEventDetails) => void)
Event handler called when the dialog is opened or closed.
((open: boolean) => void)
Event handler called after any animations complete when the dialog is opened or closed.
boolean
Whether the dialog is currently open.
string | null
ID of the trigger that the dialog is associated with. This is useful in conjunction with the open prop to create a controlled dialog. There’s no need to specify this prop when the dialog is uncontrolled (that is, when the open prop is not set).

Dialog.Trigger

string | ((state: DialogTriggerState) => string | undefined)
CSS class applied to the element, or a function that returns a class based on the component’s state.
DialogHandle<Payload>
A handle to associate the trigger with a dialog. Can be created with the Dialog.createHandle() method.
string
ID of the trigger. In addition to being forwarded to the rendered element, it is also used to specify the active trigger for the dialog in controlled mode (with the DialogRoot triggerId prop).
boolean
default:"true"
Whether the component renders a native <button> element when replacing it via the render prop. Set to false if the rendered element is not a button (for example, <div>).
Payload
A payload to pass to the dialog when it is opened.
ReactElement<unknown, string | JSXElementConstructor<any>> | ComponentRenderFn<HTMLProps, DialogTriggerState>
Allows you to replace the component’s HTML element with a different tag, or compose it with another component.Accepts a ReactElement or a function that returns the element to render.
CSSProperties | ((state: DialogTriggerState) => CSSProperties | undefined)
Style applied to the element, or a function that returns a style object based on the component’s state.

Dialog.Popup

boolean | DialogBackdropProps
default:"true"
string | ((state: DialogPopupState) => string | undefined)
CSS class applied to the element, or a function that returns a class based on the component’s state.
HTMLElement | ShadowRoot | RefObject<HTMLElement | ShadowRoot | null> | null
boolean | RefObject<HTMLElement | null> | ((closeType: InteractionType) => boolean | void | HTMLElement | null)
Determines the element to focus when the dialog is closed.
  • false: Do not move focus.
  • true: Move focus based on the default behavior (trigger or previously focused element).
  • RefObject: Move focus to the ref element.
  • function: Called with the interaction type (mouse, touch, pen, or keyboard). Return an element to focus, true to use the default behavior, null to fall back to the default behavior, or false/undefined to do nothing.
boolean | RefObject<HTMLElement | null> | ((openType: InteractionType) => boolean | void | HTMLElement | null)
Determines the element to focus when the dialog is opened. By default, focus moves to the first tabbable element inside the popup, except when the dialog is opened by touch — then the popup itself is focused to avoid opening the virtual keyboard.
  • false: Do not move focus.
  • true: Move focus based on the default behavior (first tabbable element or popup).
  • RefObject: Move focus to the ref element.
  • function: Called with the interaction type (mouse, touch, pen, or keyboard). Return an element to focus, true to use the default behavior, null to fall back to the default behavior, or false/undefined to do nothing.
boolean
ReactElement<unknown, string | JSXElementConstructor<any>> | ComponentRenderFn<HTMLProps, DialogPopupState>
Allows you to replace the component’s HTML element with a different tag, or compose it with another component.Accepts a ReactElement or a function that returns the element to render.
"fullscreen" | "lg" | "md" | "sm" | "xl"
default:"md"
CSSProperties | ((state: DialogPopupState) => CSSProperties | undefined)
Style applied to the element, or a function that returns a style object based on the component’s state.
DialogViewportProps

Dialog.Title

string | ((state: DialogTitleState) => string | undefined)
CSS class applied to the element, or a function that returns a class based on the component’s state.
"primary" | "secondary" | "tertiary"
default:"primary"
Theme font color. Defaults to primary.
1 | 2 | 3 | 4 | 5 | 6
default:"2"
Semantic heading level, from h1 through h6. Does not change the visual size. Defaults to 2.
ReactElement<unknown, string | JSXElementConstructor<any>> | ComponentRenderFn<HTMLProps, DialogTitleState>
Allows you to replace the component’s HTML element with a different tag, or compose it with another component.Accepts a ReactElement or a function that returns the element to render.
"lg" | "md" | "sm" | "xs"
default:"lg"
Visual font size, independent of the heading level. Defaults to lg.
CSSProperties | ((state: DialogTitleState) => CSSProperties | undefined)
Style applied to the element, or a function that returns a style object based on the component’s state.

Dialog.Description

string | ((state: DialogDescriptionState) => string | undefined)
CSS class applied to the element, or a function that returns a class based on the component’s state.
ReactElement<unknown, string | JSXElementConstructor<any>> | ComponentRenderFn<HTMLProps, DialogDescriptionState>
Allows you to replace the component’s HTML element with a different tag, or compose it with another component.Accepts a ReactElement or a function that returns the element to render.
CSSProperties | ((state: DialogDescriptionState) => CSSProperties | undefined)
Style applied to the element, or a function that returns a style object based on the component’s state.

Dialog.Close

string | ((state: DialogCloseState) => string | undefined)
CSS class applied to the element, or a function that returns a class based on the component’s state.
boolean
default:"true"
Whether the component renders a native <button> element when replacing it via the render prop. Set to false if the rendered element is not a button (for example, <div>).
ReactElement<unknown, string | JSXElementConstructor<any>> | ComponentRenderFn<HTMLProps, DialogCloseState>
Allows you to replace the component’s HTML element with a different tag, or compose it with another component.Accepts a ReactElement or a function that returns the element to render.
CSSProperties | ((state: DialogCloseState) => CSSProperties | undefined)
Style applied to the element, or a function that returns a style object based on the component’s state.

Dialog.Header

ReactElement<unknown, string | JSXElementConstructor<any>> | ComponentRenderFn<HTMLProps, {}>
Allows you to replace the component’s HTML element with a different tag, or compose it with another component.Accepts a ReactElement or a function that returns the element to render.

Dialog.Body

ReactElement<unknown, string | JSXElementConstructor<any>> | ComponentRenderFn<HTMLProps, {}>
Allows you to replace the component’s HTML element with a different tag, or compose it with another component.Accepts a ReactElement or a function that returns the element to render.
Allows you to replace the component’s HTML element with a different tag, or compose it with another component.Accepts a ReactElement or a function that returns the element to render.