Dialog

The React Dialog component shows a modal window on top of the page to display content or collect user input. It is used for things like forms, messages, or actions that need user attention.

It opens as an overlay and can block or allow interaction with the background. For example, you can use it to edit a profile, show details, or ask users to take an action.

Built with React and react-aria-components Components, and styled using Tailwind CSS. It supports keyboard navigation, focus management, and accessible modal behavior.

Installation

Install the component using the Tailgrids CLI.

npx @tailgrids/cli add dialog

Anatomy

Wrap the Dialog component with OverlayWrapper and Backdrop from the overlay module to create a complete dialog experience with trigger and backdrop behavior.

import { OverlayWrapper } from "@/components/tailgrids/core/overlay";
import { Backdrop } from "@/components/tailgrids/core/overlay";
import {
  Dialog,
  DialogHeader,
  DialogTitle,
  DialogDescription,
  DialogBody,
  DialogFooter,
  DialogClose
} from "@/components/tailgrids/core/dialog";

export default function DialogAnatomy() {
  return (
    <OverlayWrapper>
      <DialogTrigger />
      <Backdrop>
        <Dialog>
          <DialogHeader>
            <DialogTitle />
            <DialogDescription />
          </DialogHeader>
          <DialogBody />
          <DialogFooter>
            <DialogClose />
          </DialogFooter>
        </Dialog>
      </Backdrop>
    </OverlayWrapper>
  );
}

Examples

Basic Dialog

Wrap the Dialog component with OverlayWrapper and use Button as trigger to create a basic dialog component. Use Backdrop to render a backdrop overlay behind the dialog if needed.

Controlled Dialog

Pass isOpen and onOpenChange props to Dialog to create a controlled dialog component.

Note: OverlayWrapper is not needed when using Dialog in controlled mode.

Controlled Dialog with Backdrop

When creating a controlled dialog with a backdrop, pass the isOpen and onOpenChange props to Backdrop component.

Without Close Button

You can remove the default close button at the top using showCloseButton={false} on Dialog.

Collect Input

Present a form inside the dialog to collect user input. Use autoFocus to focus an input or action when the dialog opens.

Multiple Actions

Offer the user multiple choices or actions to select from within a single dialog.

Keep the footer actions visible while the dialog content scrolls. Useful for long content like terms of service or license agreements.

Without Overlay

Render the dialog without a backdrop overlay by omitting the Backdrop wrapper. The Dialog component renders with its own modal behavior but no visual backdrop.

Custom

Advanced Statistics

To view your performance metrics and growth forecasts, you need to unlock Pro access.

API Reference

Dialog

The root component that wraps all the content and provide dialog behavior and accessibility features.

PropTypeDefaultDescription
childrenReact.ReactNode | (opts: { close: () => void }) => React.ReactNode-Content of the dialog. Supports render props for close() access
isOpenboolean-Controlled open state
defaultOpenboolean-Uncontrolled default open state
onOpenChange(isOpen: boolean) => void-Called when the open state changes
showCloseButtonbooleantrueWhether to show the default close button in the top-right
classNamestring-Additional CSS classes for the dialog panel

DialogHeader

A semantic container for the title and description at the top of the dialog.

PropTypeDefaultDescription
childrenReact.ReactNode-Header content
classNamestring-Additional CSS classes

DialogTitle

The dialog title. Supports all heading levels via the level prop (defaults to heading level 3).

PropTypeDefaultDescription
childrenReact.ReactNode-Title text
levelnumber3Heading level (1-6)
classNamestring-Additional CSS classes

DialogDescription

A paragraph for supplementary text that describes the dialog's purpose.

PropTypeDefaultDescription
childrenReact.ReactNode-Description text
classNamestring-Additional CSS classes

DialogBody

Main content area between the header and footer.

PropTypeDefaultDescription
childrenReact.ReactNode-Body content
classNamestring-Additional CSS classes

DialogFooter

The bottom area mainly meant for actions.

PropTypeDefaultDescription
childrenReact.ReactNode-Footer content (buttons, etc.)
classNamestring-Additional CSS classes

The showCloseButton prop from the previous version has been removed from DialogFooter. Use DialogClose or a Button with slot="close" instead.

DialogClose

A button with slot="close" that automatically closes the nearest dialog when pressed. Accepts all Button props except slot.

PropTypeDefaultDescription
childrenReact.ReactNode-The close button label/content
(All Button props)-See Button API Reference

Composition

The Dialog is composed of the root Dialog component plus layout and content slots. It is paired with OverlayWrapper and Backdrop from the overlay module for trigger and backdrop behavior.

OverlayWrapper                         — Root container. Wraps DialogTrigger from RAC. Manages open/close state.
├── Button (trigger)                   — Any pressable element that opens the dialog.
├── Backdrop                           — Wraps ModalOverlay from RAC. Provides the backdrop overlay.
│   └── Dialog                         — Wraps AriaModal + AriaDialog. The dialog panel with close button.
│       ├── DialogHeader               — Container for title and description at the top.
│       │   ├── DialogTitle            — Title heading with slot="title" for ARIA labelling.
│       │   └── DialogDescription      — Supplementary description text below the title.
│       ├── DialogBody                 — Scrollable content area between header and footer.
│       └── DialogFooter               — Action bar at the bottom for buttons.
│           └── DialogClose / Button   — Close button with slot="close" that automatically closes the dialog.
  • Use OverlayWrapper (DialogTrigger from RAC) as the root. It wraps the trigger element and the dialog content and manages the open/close state.
  • Use any pressable component (e.g. Button) as the trigger child of OverlayWrapper.
  • Use Backdrop (ModalOverlay from RAC) to render a backdrop overlay. It accepts isDismissable and isKeyboardDismissDisabled props. Omit it entirely to render the dialog without a backdrop.
  • Use Dialog as the panel. It wraps AriaModal and AriaDialog, managing focus trapping and ARIA attributes. The children prop accepts a render function with a close argument for programmatic dismissal.
  • Use DialogHeader to group the title and description. It provides consistent spacing and layout.
  • Use DialogTitle rendered via Heading with slot="title". This automatically labels the dialog for screen readers.
  • Use DialogDescription for supplementary text. It is positioned below the title inside the header.
  • Use DialogBody for the main scrollable content area.
  • Use DialogFooter for action buttons. Use DialogClose or any Button with slot="close" for custom close triggers.
  • Use DialogClose to render a Button with slot="close". It automatically closes the nearest dialog when pressed.

Accessibility

  • Focus management: The dialog keeps focus while open and returns focus to the trigger when it closes.
  • Keyboard support: Users can press the Escape key to close the dialog. You can turn off this behavior by setting isKeyboardDismissDisabled on Backdrop.
  • Trigger behavior: Users can open and close the dialog using a trigger or a close button with a mouse or keyboard.
  • Screen reader support: Screen readers announce the dialog as a modal, and background content stays hidden while it is open.
  • ARIA labeling: Use DialogTitle and DialogDescription to describe the dialog content clearly.
  • Outside click: Users can close the dialog by clicking outside when isDismissable is enabled on Backdrop.
  • Dialog role: The Dialog component renders with role="dialog" by default. Use role="alertdialog" for alert dialogs via the role prop.