DocsBlog

Get Started

Components

Data Grid

Signals

Styling

Theming

↑↓Navigate
↵Select
EscClose
  • 1.8.0

  • Day

    Night

    Preview

    Switch mode
  • cerberus

    acheron

    elysium

    oceanus

Get Started
Components
Data Grid
Signals
Styling
Theming

Concepts

OverviewCompositionCerberus ContextTesting

Layout

Aspect RatioBleedBoxCenterContainerContainer QueryDividerFlexFloatGridGroupLink OverlayScrollableStackWrap

Components

AccordionAdmonitionAvatarButtonCarouselCheckboxClipboardCollapsibleComboboxConfirm ModalCTA ModalDate PickerDialogFieldFieldsetFile UploaderIconButtonInputLoading StatesMarqueeMenuNotificationsNumber InputPaginationPin InputPopoverProgress IndicatorsPrompt ModalRadioRatingSelectSliderSplit ButtonSwitchTableTabsTagTextTextareaToggleTooltip

Utilities

Client OnlyDownload TriggerEnvironmentFeature FlagsFocus TrapForFormat ByteFormat NumberFormat Relative TimeFormat Relative TimeFrameHighlightJSON Tree ViewLocalePortalPresenceShowSwapsplitPropsTheme

Dialog

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

  • npm
  • source
  • recipe
  • Ark
View as Markdown
Open this page in Markdown
Anthropic
Open in Claude
Ask questions about this page
OpenAI
Open in ChatGPT
Ask questions about this page

Import

import {
  Dialog,
  DialogTrigger,
  DialogHeading,
  DialogDescription,
  DialogCloseTrigger,
  DialogCloseIconTrigger,
} from '@cerberus-design/react'

Usage

To use the Dialog component, wrap it in a DialogProvider and use the DialogTrigger component to open the dialog. The Dialog component is a controlled component that can be used to display content in a modal.

Loading example...

Sizes

The Dialog component supports different sizes. You can set the size prop to xs to lg, or full.

Loading example...

Controlled

Manage the dialog state using the open and onOpenChange props.

Note

Notice how the dialog triggers automagically handle the state management via onOpenChange.

Loading example...

Root Provider

An alternative way to control the dialog is to use the RootProvider component and the useDialog hook. This way you can access the state and methods from outside the component.

Loading example...

Lazy Mount

Use lazyMount to render dialog content only when first opened. Combine with unmountOnExit to unmount when closed, freeing up resources.

Prefer this over conditionally rendering DialogProvider — see Conditional Rendering.

Loading example...

Inside Scroll

Make the content area scrollable while keeping header and footer fixed using maxHeight and overflow: auto.

Loading example...

Outside Scroll

Make the positioner scrollable so the dialog can extend beyond the viewport.

Loading example...

Initial Focus

Use initialFocusEl to control which element receives focus when the dialog opens.

Loading example...

Final Focus

Use finalFocusEl to control which element receives focus when the dialog closes. Defaults to the trigger element.

Loading example...

Context

Access the dialog's state and methods with DialogContext or the useDialogContext hook.

Loading example...

Open from Menu

Open a dialog imperatively from a Menu item using the onClick handler.

Loading example...

Nested

Nest dialogs within one another. The parent receives data-has-nested and --nested-layer-count CSS variable for styling effects like zoom-out:

[data-part='content'][data-has-nested] {
  transform: scale(calc(1 - var(--nested-layer-count) * 0.05));
}

Loading example...

Confirmation

Intercept close attempts to show confirmation prompts, preventing data loss from unsaved changes.

Loading example...

Non-Modal

We don't recommend using a non-modal dialog due to the accessibility concerns they present. In event you need it, here's what you can do:

  • set the modal prop to false
  • set pointerEvents to none on the Dialog.Positioner component
  • (optional) set the closeOnInteractOutside prop to false Preview
Loading example...

Guides

Close Behavior

  • closeOnEscape={false} - Prevent closing on Escape
  • closeOnInteractOutside={false} - Prevent closing on outside click

For conditional control, use onEscapeKeyDown or onInteractOutside with e.preventDefault().

Conditional Rendering

Unmounting Dialog.Root when toggling open state can break focus, scroll lock, and cleanup. Keep the root mounted and control it with open / onOpenChange.

When you want portal content out of the DOM while closed, add lazyMount and unmountOnExit to the root.

Loading example...

Z-index Stacking

Use the --layer-index CSS variable for z-index management of stacked dialogs:

[data-part='content'] {
  z-index: calc(var(--layer-index));
}

Dynamic Imports

When using lazyMount with lazy or Next.js dynamic, wrap the imported component in Suspense:

Loading example...

Customizing

You can customize the Dialog using style props and data selectors on any slot primitve.

Primitives

You can utilize the primitive components or the css prop to customize the dialog.

ComponentDescription
DialogProviderThe main state context for the dialog.
DialogTriggerThe trigger element that opens the dialog.
DialogBackdropThe backdrop that covers the page when the dialog is open.
DialogPositionerThe container that positions the dialog content.
DialogContentThe content that is shown within the dialog.
DialogHeadingThe heading title of the dialog.
DialogDescriptionThe description of the dialog.
DialogCloseTriggerThe trigger element that closes the dialog.
DialogCloseIconTriggerThe trigger element that closes the dialog with an "x" icon.

API

Props

The Dialog component is an abstraction of the primitives and accepts the following props:

Root Props:

PropTypeRequiredDescription
aria-labelstringNoHuman readable label for the dialog, in event the dialog title is not rendered
closeOnEscapebooleanNoWhether to close the dialog when the escape key is pressed
closeOnInteractOutsidebooleanNoWhether to close the dialog when the outside is clicked
defaultOpenbooleanNoThe initial open state of the dialog when rendered. Use when you don't need to control the open state of the dialog.
finalFocusEl() => MaybeElementNoElement to receive focus when the dialog is closed
idstringNoThe unique identifier of the machine.
idsPartial<PrimitiveLayers>NoThe ids of the elements in the dialog. Useful for composition.
immediatebooleanNoWhether to synchronize the present change immediately or defer it to the next frame
initialFocusEl() => MaybeElementNoElement to receive focus when the dialog is opened
lazyMountbooleanNoWhether to enable lazy mounting
modalbooleanNoWhether to prevent pointer interaction outside the element and hide all content below it
onEscapeKeyDown(event: KeyboardEvent) => voidNoFunction called when the escape key is pressed
onExitCompleteVoidFunctionNoFunction called when the animation ends in the closed state
onFocusOutside(event: FocusOutsideEvent) => voidNoFunction called when the focus is moved outside the component
onInteractOutside(event: InteractOutsideEvent) => voidNoFunction called when an interaction happens outside the component
onOpenChange(details: OpenChangeDetails) => voidNoFunction to call when the dialog's open state changes
onPointerDownOutside(event: PointerDownOutsideEvent) => voidNoFunction called when the pointer is pressed down outside the component
onRequestDismiss(event: LayerDismissEvent) => voidNoFunction called when this layer is closed due to a parent layer being closed
openbooleanNoThe controlled open state of the dialog
persistentElements(() => Element | null)[]NoReturns the persistent elements that: should not have pointer-events disabled or should not trigger the dismiss event
presentbooleanNoWhether the node is present (controlled by the user)
preventScrollbooleanNoWhether to prevent scrolling behind the dialog when it's opened
restoreFocusbooleanNoWhether to restore focus to the element that had focus before the dialog was opened
role'dialog' | 'alertdialog'NoThe dialog's role
skipAnimationOnMountbooleanNoWhether to allow the initial presence animation.
sizestringNoThis size of the Dialog.
trapFocusbooleanNoWhether to trap focus inside the dialog when it's opened
unmountOnExitbooleanNoWhether to unmount on exit.

Backdrop Props:

PropTypeRequiredDescription
asChildbooleanNoUse the provided child element as the default rendered element, combining their props and behavior.

Backdrop Data Attributes:

AttributeValue
[data-scope]dialog
[data-part]backdrop
[data-state]"open" | "closed"

Backdrop CSS Variables:

VariableDescription
--layer-indexThe index of the dismissable in the layer stack

CloseTrigger Props:

PropTypeRequiredDescription
asChildbooleanNoUse the provided child element as the default rendered element, combining their props and behavior.

Content Props:

PropTypeRequiredDescription
asChildbooleanNoUse the provided child element as the default rendered element, combining their props and behavior.

Content Data Attributes:

AttributeValue
[data-scope]dialog
[data-part]content
[data-state]"open" | "closed"
[data-nested]dialog
[data-has-nested]dialog

Content CSS Variables:

VariableDescription
--layer-indexThe index of the dismissable in the layer stack
--nested-layer-countThe number of nested dialogs

Description Props:

PropTypeRequiredDescription
asChildbooleanNoUse the provided child element as the default rendered element, combining their props and behavior.

Positioner Props:

PropTypeRequiredDescription
asChildbooleanNoUse the provided child element as the default rendered element, combining their props and behavior.

RootProvider Props

PropTypeRequiredDescription
valueUseDialogReturnYes
asChildbooleanNoUse the provided child element as the default rendered element, combining their props and behavior.
immediatebooleanNoWhether to synchronize the present change immediately or defer it to the next frame
lazyMountbooleanNoWhether to enable lazy mounting
onExitCompleteVoidFunctionNoFunction called when the animation ends in the closed state
presentbooleanNoWhether the node is present (controlled by the user)
skipAnimationOnMountbooleanNoWhether to allow the initial presence animation.
unmountOnExitbooleanNoWhether to unmount on exit.

Title Props:

PropTypeRequiredDescription
asChildbooleanNoUse the provided child element as the default rendered element, combining their props and behavior.

Trigger Props

PropTypeRequiredDescription
asChildbooleanNoUse the provided child element as the default rendered element, combining their props and behavior.

Trigger Data Attributes

AttributeValue
[data-scope]dialog
[data-part]trigger
[data-value]The value of the item
[data-state]"open" | "closed"
[data-current]Present when current

On this page

  • Import
  • Usage
    • Sizes
    • Controlled
    • Root Provider
    • Lazy Mount
    • Inside Scroll
    • Outside Scroll
    • Initial Focus
    • Final Focus
    • Context
    • Open from Menu
    • Nested
    • Confirmation
    • Non-Modal
  • Guides
    • Close Behavior
    • Conditional Rendering
    • Z-index Stacking
    • Dynamic Imports
    • Customizing
  • Primitives
  • API
    • Props
      • Root Props:
      • Backdrop Props:
      • Backdrop Data Attributes:
      • Backdrop CSS Variables:
      • CloseTrigger Props:
      • Content Props:
      • Content Data Attributes:
      • Content CSS Variables:
      • Description Props:
      • Positioner Props:
      • RootProvider Props
      • Title Props:
      • Trigger Props
      • Trigger Data Attributes
Edit this page on Github

Dialog Title

Far far away, behind the word mountains, far from the countries Vokalia and Consonantia, there live the blind texts. Separated they live in Bookmarksgrove right at the coast of the Semantics, a large language ocean.

Dialog Title

Far far away, behind the word mountains, far from the countries Vokalia and Consonantia, there live the blind texts. Separated they live in Bookmarksgrove right at the coast of the Semantics, a large language ocean.

Dialog Title

Far far away, behind the word mountains, far from the countries Vokalia and Consonantia, there live the blind texts. Separated they live in Bookmarksgrove right at the coast of the Semantics, a large language ocean.

Dialog Title

Far far away, behind the word mountains, far from the countries Vokalia and Consonantia, there live the blind texts. Separated they live in Bookmarksgrove right at the coast of the Semantics, a large language ocean.

Dialog Title

Far far away, behind the word mountains, far from the countries Vokalia and Consonantia, there live the blind texts. Separated they live in Bookmarksgrove right at the coast of the Semantics, a large language ocean.

Dialog Title

Far far away, behind the word mountains, far from the countries Vokalia and Consonantia, there live the blind texts. Separated they live in Bookmarksgrove right at the coast of the Semantics, a large language ocean.

Dialog Title

Far far away, behind the word mountains, far from the countries Vokalia and Consonantia, there live the blind texts. Separated they live in Bookmarksgrove right at the coast of the Semantics, a large language ocean.

Dialog Title

Far far away, behind the word mountains, far from the countries Vokalia and Consonantia, there live the blind texts. Separated they live in Bookmarksgrove right at the coast of the Semantics, a large language ocean.

Controlled Externally

This dialog is controlled via the useDialog hook.

Dialog Title

1. Acceptance of Terms

By accessing and using this service, you accept and agree to be bound by the terms and provisions of this agreement.

2. Use License

Permission is granted to temporarily use this service for personal, non-commercial purposes only. This is the grant of a license, not a transfer of title.

3. User Responsibilities

You are responsible for maintaining the confidentiality of your account and password. You agree to accept responsibility for all activities that occur under your account.

4. Privacy Policy

Your use of this service is also governed by our Privacy Policy. Please review our Privacy Policy, which also governs the site and informs users of our data collection practices.

5. Limitations

In no event shall we be liable for any damages arising out of the use or inability to use the materials on this service.

6. Revisions

We may revise these terms of service at any time without notice. By using this service you are agreeing to be bound by the then current version of these terms.

7. Governing Law

These terms and conditions are governed by and construed in accordance with applicable laws and you irrevocably submit to the exclusive jurisdiction of the courts.

Dialog Title

1. Acceptance of Terms

By accessing and using this service, you accept and agree to be bound by the terms and provisions of this agreement.

2. Use License

Permission is granted to temporarily use this service for personal, non-commercial purposes only. This is the grant of a license, not a transfer of title.

3. User Responsibilities

You are responsible for maintaining the confidentiality of your account and password. You agree to accept responsibility for all activities that occur under your account.

4. Privacy Policy

Your use of this service is also governed by our Privacy Policy. Please review our Privacy Policy, which also governs the site and informs users of our data collection practices.

5. Limitations

In no event shall we be liable for any damages arising out of the use or inability to use the materials on this service.

6. Revisions

We may revise these terms of service at any time without notice. By using this service you are agreeing to be bound by the then current version of these terms.

7. Governing Law

These terms and conditions are governed by and construed in accordance with applicable laws and you irrevocably submit to the exclusive jurisdiction of the courts.

Edit Profile

The first input will be focused when the dialog opens.

I will receive focus when dialog closes

Dialog Title

Far far away, behind the word mountains, far from the countries Vokalia and Consonantia, there live the blind texts. Separated they live in Bookmarksgrove right at the coast of the Semantics, a large language ocean.

Status

Dialog is closed

Edit
Duplicate

Delete

Dialog Title

Far far away, behind the word mountains, far from the countries Vokalia and Consonantia, there live the blind texts. Separated they live in Bookmarksgrove right at the coast of the Semantics, a large language ocean.

Parent Dialog

This is the parent dialog. Open a nested dialog to see automatic z-index management.

Nested Dialog

This dialog is nested within the parent with proper z-index layering.

Edit Content

Make changes to your content. You'll be asked to confirm before closing if there are unsaved changes.

Unsaved Changes

You have unsaved changes. Are you sure you want to close without saving?

Dialog Title

Far far away, behind the word mountains, far from the countries Vokalia and Consonantia, there live the blind texts. Separated they live in Bookmarksgrove right at the coast of the Semantics, a large language ocean.
Copy
import { DialogRoot, type OpenChangeDetails, Portal } from '@cerberus/react/react'
import { useSignal } from '@cerberus/react/signals'

// ❌ Avoid
export function Dont() {
  const [isOpen, setOpen] = useSignal<boolean>(false)

  if (isOpen) {
    return (
      <DialogRoot
        open={isOpen}
        onOpenChange={(e: OpenChangeDetails) => setOpen(e.open)}
      >
        <Portal>...</Portal>
      </DialogRoot>
    )
  }

  return null
}

// ✅ Prefer
export function Do() {
  const [isOpen, setOpen] = useSignal<boolean>(false)
  return (
    <DialogRoot
      open={isOpen}
      onOpenChange={(e: OpenChangeDetails) => setOpen(e.open)}
      lazyMount
      unmountOnExit
    >
      <Portal>...</Portal>
    </DialogRoot>
  )
}
Copy
import { Dialog, DialogProvider, DialogTrigger } from '@cerberus/react/react'
import dynamic from 'next/dynamic'
import { Suspense } from 'react'

const HeavyComponent = dynamic(() => import('./heavy'))

export function DynamicDemo() {
  return (
    <DialogProvider lazyMount>
      <DialogTrigger>Open</DialogTrigger>
      <Dialog>
        <Suspense fallback={<div>Loading...</div>}>
          <HeavyComponent />
        </Suspense>
      </Dialog>
    </DialogProvider>
  )
}