Dialog

A popup that opens on top of the entire page.

API reference

Import the component and assemble its parts:

Anatomy
import { Dialog } from '@base-ui-components/react/dialog';

<Dialog.Root>
  <Dialog.Trigger />
  <Dialog.Portal>
    <Dialog.Backdrop />
    <Dialog.Popup>
      <Dialog.Title />
      <Dialog.Description />
      <Dialog.Close />
    </Dialog.Popup>
  </Dialog.Portal>
</Dialog.Root>

Root

Groups all parts of the dialog. Doesn’t render its own HTML element.

PropTypeDefault
defaultOpen

boolean

false

open

boolean

undefined

onOpenChange

(open, event, reason) => void

undefined

dismissible

boolean

true

modal

boolean

true

Trigger

A button that opens the dialog. Renders a <button> element.

PropTypeDefault
className

string | (state) => string

undefined

render

| React.ReactElement
| (props, state) => React.ReactElement

undefined

Attribute
Description
data-popup-open

Portal

A portal element that moves the popup to a different part of the DOM. By default, the portal element is appended to <body>.

PropTypeDefault
container

React.Ref | HTMLElement | null

undefined

keepMounted

boolean

false

Backdrop

An overlay displayed beneath the popup. Renders a <div> element.

PropTypeDefault
className

string | (state) => string

undefined

keepMounted

boolean

false

render

| React.ReactElement
| (props, state) => React.ReactElement

undefined

Attribute
Description
data-open
data-closed
data-starting-style
data-ending-style

A container for the dialog contents. Renders a <div> element.

PropTypeDefault
initialFocus

| React.Ref
| (interactionType => HTMLElement | null)

undefined

finalFocus

React.Ref

undefined

className

string | (state) => string

undefined

keepMounted

boolean

false

render

| React.ReactElement
| (props, state) => React.ReactElement

undefined

Attribute
Description
data-open
data-closed
data-has-nested-dialogs
data-nested
data-starting-style
data-ending-style
CSS Variable
Description
--nested-dialogs

Title

A heading that labels the dialog. Renders an <h2> element.

PropTypeDefault
className

string | (state) => string

undefined

render

| React.ReactElement
| (props, state) => React.ReactElement

undefined

Description

A paragraph with additional information about the dialog. Renders a <p> element.

PropTypeDefault
className

string | (state) => string

undefined

render

| React.ReactElement
| (props, state) => React.ReactElement

undefined

Close

A button that closes the dialog. Renders a <button> element.

PropTypeDefault
className

string | (state) => string

undefined

render

| React.ReactElement
| (props, state) => React.ReactElement

undefined

Examples

State

By default, Dialog is an uncontrolled component that manages its own state.

Uncontrolled dialog
<Dialog.Root>
  <Dialog.Trigger>Open</Dialog.Trigger>
  <Dialog.Portal>
    <Dialog.Popup>
      <Dialog.Title>Example dialog</Dialog.Title>
      <Dialog.Close>Close</Dialog.Close>
    </Dialog.Popup>
  </Dialog.Portal>
</Dialog.Root>

Use open and onOpenChange props if you need to access or control the state of the dialog.

Controlled dialog
const [open, setOpen] = React.useState(false);
return (
  <Dialog.Root open={open} onOpenChange={setOpen}>
    <Dialog.Trigger>Open</Dialog.Trigger>
    <Dialog.Portal>
      <Dialog.Popup>
        <form
          // Close the dialog once the form data is submitted
          onSubmit={async () => {
            await submitData();
            setOpen(false);
          }}
        >
          ...
        </form>
      </Dialog.Popup>
    </Dialog.Portal>
  </Dialog.Root>
);

It’s also common to use onOpenChange if your app needs to do something when the dialog is closed or opened. This is recommended over React.useEffect when reacting to state changes.

Running code when dialog state changes
<Dialog.Root
  open={open}
  onOpenChange={(open) => {
    // Do stuff when the dialog is closed
    if (!open) {
      doStuff();
    }
    // Set the new state
    setOpen(open);
  }}
>