Dialog
A window overlaid on either the primary window or another dialog window, rendering the content underneath inert.
Anatomy
Import and assemble the component:
1import { Dialog } from '@raystack/apsara'23<Dialog>4 <Dialog.Trigger />5 <Dialog.Content>6 <Dialog.Header>7 <Dialog.Title />8 <Dialog.CloseButton />9 </Dialog.Header>10 <Dialog.Body>11 <Dialog.Description />12 </Dialog.Body>13 <Dialog.Footer />14 </Dialog.Content>15</Dialog>
Usage
Controlled Dialog
Pass open with onOpenChange to own the state — needed when the dialog must close on something other than a click, such as a save completing.
1(function ControlledDialog() {2 const [open, setOpen] = React.useState(false);34 return (5 <Dialog open={open} onOpenChange={setOpen}>6 <Dialog.Trigger render={<Button />}>Controlled Dialog</Dialog.Trigger>7 <Dialog.Content style={{ width: 600 }}>8 <Dialog.Body>9 <Dialog.Title>Controlled State</Dialog.Title>10 <Dialog.Description>11 This dialog's state is controlled externally.12 </Dialog.Description>13 </Dialog.Body>14 </Dialog.Content>15 </Dialog>
Custom width and overlay
Example with custom width and overlay styling.
1<Dialog>2 <Dialog.Trigger render={<Button />}>Styled Dialog</Dialog.Trigger>3 <Dialog.Content4 style={{ width: "400px" }}5 overlay={{6 blur: true,7 className: "custom-overlay",8 style: { backgroundColor: "oklch(0 0 0 / 0.5)" },9 }}10 >11 <Dialog.Body>12 <Dialog.Title>Custom Styled Dialog</Dialog.Title>13 <Dialog.Description className="custom-description">14 This dialog has custom width and overlay styling.15 </Dialog.Description>
With header and body
Dialog.Header carries the title and the close control; Dialog.Body holds the content. Leave the footer out when the dialog only presents information and closing is the only action.
1<Dialog>2 <Dialog.Trigger render={<Button />}>Only Header and Body</Dialog.Trigger>3 <Dialog.Content4 style={{ width: "400px" }}5 overlay={{6 blur: true,7 className: "custom-overlay",8 style: { backgroundColor: "oklch(0 0 0 / 0.5)" },9 }}10 >11 <Dialog.Header>12 <Dialog.Title>Title</Dialog.Title>13 </Dialog.Header>14 <Dialog.Body>15 <Dialog.Description className="custom-description">
With body and footer
Skip the header when the body opens with its own heading. Dialog.Footer pins the actions to the bottom edge, separated from content that scrolls.
1<Dialog>2 <Dialog.Trigger render={<Button />}>Only Footer and Body</Dialog.Trigger>3 <Dialog.Content4 style={{ width: "400px" }}5 overlay={{6 blur: true,7 className: "custom-overlay",8 style: { backgroundColor: "oklch(0 0 0 / 0.5)" },9 }}10 >11 <Dialog.Body>12 <Dialog.Title>Title</Dialog.Title>13 <Dialog.Description className="custom-description">14 This dialog has custom width and overlay styling.15 </Dialog.Description>
Nested dialogs
You can nest dialogs within one another. When a nested dialog opens, the parent dialog automatically scales down and becomes slightly transparent. The nested dialog's backdrop won't be rendered, allowing you to see the parent dialog behind it.
1(function NestedDialogExample() {2 const [parentOpen, setParentOpen] = React.useState(false);3 const [nestedOpen, setNestedOpen] = React.useState(false);45 return (6 <>7 <Dialog open={parentOpen} onOpenChange={setParentOpen}>8 <Dialog.Trigger render={<Button />}>Open Parent Dialog</Dialog.Trigger>9 <Dialog.Content style={{ width: 400 }}>10 <Dialog.Header>11 <Dialog.Title>Parent Dialog</Dialog.Title>12 </Dialog.Header>13 <Dialog.Body>14 <Dialog.Description>15 This is the parent dialog. Click the button below to open a nested
API Reference
Root
Groups all parts of the dialog.
Prop
Type
Content
Renders the dialog panel overlay.
Prop
Type
Header
Renders the dialog header section.
Prop
Type
Title
Renders the dialog title text.
Prop
Type
Body
Renders the main content area of the dialog.
Prop
Type
Description
Renders supplementary text within the dialog body.
Prop
Type
Trigger
Renders the element that opens the dialog.
Prop
Type
CloseButton
Renders a button that closes the dialog.
Prop
Type
Footer
Renders the dialog footer section.
Prop
Type
Slots
Every rendered part carries a stable data-slot attribute for styling and testing:
| Slot | Element |
|---|---|
dialog-backdrop | The overlay behind the dialog |
dialog-viewport | Viewport wrapper that positions the dialog |
dialog-content | The dialog popup |
dialog-header | The Dialog.Header row |
dialog-title | The Dialog.Title element |
dialog-body | The Dialog.Body container |
dialog-description | The Dialog.Description element |
dialog-footer | The Dialog.Footer row |
dialog-close | The built-in close button (when showCloseButton) |
Accessibility
- Dialog has
role="dialog"andaria-modal="true" - Uses
aria-labeloraria-labelledbyto identify the dialog - Uses
aria-describedbyto provide additional context - Respects motion preferences: dialog panel motion is enabled only when
prefers-reduced-motion: no-preference