Dialog

A modal window that appears on top of the main content.

Anatomy

To use the dialog component correctly, you’ll need to understand its anatomy and how we name its parts.

Each part includes a data-part attribute to help identify them in the DOM.

Examples

Learn how to use the Dialog component in your project. Let’s take a look at the most basic example

import { Dialog, Portal } from '@ark-ui/react'

const Basic = () => (
  <Dialog.Root>
    <Dialog.Trigger>Open Dialog</Dialog.Trigger>
    <Portal>
      <Dialog.Backdrop />
      <Dialog.Positioner>
        <Dialog.Content>
          <Dialog.Title>Dialog Title</Dialog.Title>
          <Dialog.Description>Dialog Description</Dialog.Description>
          <Dialog.CloseTrigger>Close</Dialog.CloseTrigger>
        </Dialog.Content>
      </Dialog.Positioner>
    </Portal>
  </Dialog.Root>
)

Controlled Dialog

To create a controlled Dialog component, manage the state of the dialog using the open and onOpenChange props:

import { Dialog, Portal } from '@ark-ui/react'
import { useState } from 'react'

const Controlled = () => {
  const [isOpen, setIsOpen] = useState(false)
  return (
    <>
      <button onClick={() => setIsOpen(true)}>Open Dialog</button>
      <Dialog.Root open={isOpen} onOpenChange={(e) => setIsOpen(e.open)}>
        <Portal>
          <Dialog.Backdrop />
          <Dialog.Positioner>
            <Dialog.Content>
              <Dialog.Title>Dialog Title</Dialog.Title>
              <Dialog.Description>Dialog Description</Dialog.Description>
              <Dialog.CloseTrigger>Close</Dialog.CloseTrigger>
            </Dialog.Content>
          </Dialog.Positioner>
        </Portal>
      </Dialog.Root>
    </>
  )
}

Lazy Mounting

Lazy mounting is a feature that allows the content of a dialog to be rendered only when the dialog is first opened. This is useful for performance optimization, especially when dialog content is large or complex. To enable lazy mounting, use the lazyMount prop on the Dialog.Root component.

In addition, the unmountOnExit prop can be used in conjunction with lazyMount to unmount the dialog content when the Dialog is closed, freeing up resources. The next time the dialog is activated, its content will be re-rendered.

import { Dialog, Portal } from '@ark-ui/react'

const LazyMount = () => (
  <Dialog.Root lazyMount unmountOnExit onExitComplete={() => console.log('onExitComplete invoked')}>
    <Dialog.Trigger>Open Dialog</Dialog.Trigger>
    <Portal>
      <Dialog.Backdrop />
      <Dialog.Positioner>
        <Dialog.Content>
          <Dialog.Title>Dialog Title</Dialog.Title>
          <Dialog.Description>Dialog Description</Dialog.Description>
          <Dialog.CloseTrigger>Close</Dialog.CloseTrigger>
        </Dialog.Content>
      </Dialog.Positioner>
    </Portal>
  </Dialog.Root>
)

Using Render Function

The Dialog component supports the use of a render function as a child for more control. This allows access to dialog states like isOpen:

import { Dialog, Portal } from '@ark-ui/react'

const RenderFn = () => (
  <Dialog.Root>
    {({ isOpen }) => (
      <>
        <Dialog.Trigger>Open Dialog</Dialog.Trigger>
        <Portal>
          <Dialog.Backdrop />
          <Dialog.Positioner>
            <Dialog.Content>
              <Dialog.Title>Dialog Title</Dialog.Title>
              <Dialog.Description>Dialog Description</Dialog.Description>
              <Dialog.CloseTrigger>Close</Dialog.CloseTrigger>
            </Dialog.Content>
          </Dialog.Positioner>
        </Portal>
        <p>Dialog is {isOpen ? 'open' : 'closed'}</p>
      </>
    )}
  </Dialog.Root>
)

API Reference

Root

PropTypeDefault
aria-label
string
closeOnEscapeKeyDown
boolean
closeOnInteractOutside
boolean
defaultOpen
boolean
dir
'ltr' | 'rtl'"ltr"
finalFocusEl
HTMLElement | (() => MaybeElement)
getRootNode
() => Node | ShadowRoot | Document
id
string
ids
Partial<{ trigger: string positioner: string backdrop: string content: string closeTrigger: string title: string description: string }>
initialFocusEl
HTMLElement | (() => MaybeElement)
lazyMount
booleanfalse
modal
boolean
onEscapeKeyDown
(event: KeyboardEvent) => void
onExitComplete
() => void
onFocusOutside
(event: FocusOutsideEvent) => void
onInteractOutside
(event: InteractOutsideEvent) => void
onOpenChange
(details: OpenChangeDetails) => void
onPointerDownOutside
(event: PointerDownOutsideEvent) => void
open
boolean
present
boolean
preventScroll
boolean
restoreFocus
boolean
role
'dialog' | 'alertdialog'"dialog"
trapFocus
boolean
unmountOnExit
booleanfalse

Title

PropTypeDefault
asChild
boolean

Content

PropTypeDefault
asChild
boolean

Trigger

PropTypeDefault
asChild
boolean

Backdrop

PropTypeDefault
asChild
boolean

Positioner

PropTypeDefault
asChild
boolean

Description

PropTypeDefault
asChild
boolean

CloseTrigger

PropTypeDefault
asChild
boolean