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'
2
3<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>

API Reference

Root

Groups all parts of the dialog.

Prop

Type

Content

Renders the dialog panel overlay.

Prop

Type

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

Renders the dialog footer section.

Prop

Type

Examples

Controlled Dialog

Example of a controlled dialog with custom state management.

1(function ControlledDialog() {
2 const [open, setOpen] = React.useState(false);
3
4 return (
5 <Dialog open={open} onOpenChange={setOpen}>
6 <Dialog.Trigger render={<Button />}>Controlled Dialog</Dialog.Trigger>
7 <Dialog.Content 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.Content
4 width="400px"
5 overlay={{
6 blur: true,
7 className: "custom-overlay",
8 style: { backgroundColor: "rgba(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

Example with header and body.

1<Dialog>
2 <Dialog.Trigger render={<Button />}>Only Header and Body</Dialog.Trigger>
3 <Dialog.Content
4 width="400px"
5 overlay={{
6 blur: true,
7 className: "custom-overlay",
8 style: { backgroundColor: "rgba(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">

Example with header and body.

1<Dialog>
2 <Dialog.Trigger render={<Button />}>Only Footer and Body</Dialog.Trigger>
3 <Dialog.Content
4 width="400px"
5 overlay={{
6 blur: true,
7 className: "custom-overlay",
8 style: { backgroundColor: "rgba(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);
4
5 return (
6 <>
7 <Dialog open={parentOpen} onOpenChange={setParentOpen}>
8 <Dialog.Trigger render={<Button />}>Open Parent Dialog</Dialog.Trigger>
9 <Dialog.Content 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

Accessibility

  • Dialog has role="dialog" and aria-modal="true"
  • Uses aria-label or aria-labelledby to identify the dialog
  • Uses aria-describedby to provide additional context