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 dialogAnatomy
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.
Sticky Footer
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.
| Prop | Type | Default | Description |
|---|---|---|---|
children | React.ReactNode | (opts: { close: () => void }) => React.ReactNode | - | Content of the dialog. Supports render props for close() access |
isOpen | boolean | - | Controlled open state |
defaultOpen | boolean | - | Uncontrolled default open state |
onOpenChange | (isOpen: boolean) => void | - | Called when the open state changes |
showCloseButton | boolean | true | Whether to show the default close button in the top-right |
className | string | - | Additional CSS classes for the dialog panel |
DialogHeader
A semantic container for the title and description at the top of the dialog.
| Prop | Type | Default | Description |
|---|---|---|---|
children | React.ReactNode | - | Header content |
className | string | - | Additional CSS classes |
DialogTitle
The dialog title. Supports all heading levels via the level prop (defaults to heading level 3).
| Prop | Type | Default | Description |
|---|---|---|---|
children | React.ReactNode | - | Title text |
level | number | 3 | Heading level (1-6) |
className | string | - | Additional CSS classes |
DialogDescription
A paragraph for supplementary text that describes the dialog's purpose.
| Prop | Type | Default | Description |
|---|---|---|---|
children | React.ReactNode | - | Description text |
className | string | - | Additional CSS classes |
DialogBody
Main content area between the header and footer.
| Prop | Type | Default | Description |
|---|---|---|---|
children | React.ReactNode | - | Body content |
className | string | - | Additional CSS classes |
DialogFooter
The bottom area mainly meant for actions.
| Prop | Type | Default | Description |
|---|---|---|---|
children | React.ReactNode | - | Footer content (buttons, etc.) |
className | string | - | 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.
| Prop | Type | Default | Description |
|---|---|---|---|
children | React.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(DialogTriggerfrom 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 ofOverlayWrapper. - Use
Backdrop(ModalOverlayfrom RAC) to render a backdrop overlay. It acceptsisDismissableandisKeyboardDismissDisabledprops. Omit it entirely to render the dialog without a backdrop. - Use
Dialogas the panel. It wrapsAriaModalandAriaDialog, managing focus trapping and ARIA attributes. Thechildrenprop accepts a render function with acloseargument for programmatic dismissal. - Use
DialogHeaderto group the title and description. It provides consistent spacing and layout. - Use
DialogTitlerendered viaHeadingwithslot="title". This automatically labels the dialog for screen readers. - Use
DialogDescriptionfor supplementary text. It is positioned below the title inside the header. - Use
DialogBodyfor the main scrollable content area. - Use
DialogFooterfor action buttons. UseDialogCloseor anyButtonwithslot="close"for custom close triggers. - Use
DialogCloseto render aButtonwithslot="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
Escapekey to close the dialog. You can turn off this behavior by settingisKeyboardDismissDisabledonBackdrop. - 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
DialogTitleandDialogDescriptionto describe the dialog content clearly. - Outside click: Users can close the dialog by clicking outside when
isDismissableis enabled onBackdrop. - Dialog role: The
Dialogcomponent renders withrole="dialog"by default. Userole="alertdialog"for alert dialogs via theroleprop.
