Dialog
The Dialog component displays content in a modal overlay. It can be used for confirmations, forms, alerts, and other interactions that require the user’s attention before returning to the underlying page.
import { createEffect, createSignal } from "solid-js";
import Button from "rocksolidjs/Button";
import Dialog from "rocksolidjs/Dialog";
import DialogActions from "rocksolidjs/DialogActions";
import DialogContent from "rocksolidjs/DialogContent";
import DialogTitle from "rocksolidjs/DialogTitle";
export default function Example() {
const [open, setOpen] = createSignal(false);
let openButton!: HTMLButtonElement,
closeBtn!: HTMLButtonElement;
createEffect(() => {
if (open()) {
closeBtn.focus();
}
});
const handleDialogClose = () => {
setOpen(false);
openButton.focus();
};
return (
<>
<Button
ref={openButton}
onClick={() => setOpen(true)}
>
Open dialog
</Button>
<Dialog
open={open()}
aria-labelledby="getting-started-dialog-title"
onClose={handleDialogClose}
class="max-w-md"
>
<DialogTitle id="getting-started-dialog-title">
Getting Started
</DialogTitle>
<DialogContent>
Complete the setup to access all available features.
</DialogContent>
<DialogActions>
<Button
ref={closeBtn}
onClick={handleDialogClose}
>
Close
</Button>
</DialogActions>
</Dialog>
</>
);
}Examples
Open
Use the open prop to control whether the dialog is visible. Place the
interactive content inside the dialog and use DialogActions for actions
such as canceling or confirming an operation.
import { createEffect, createSignal } from "solid-js";
import Button from "rocksolidjs/Button";
import Dialog from "rocksolidjs/Dialog";
import DialogActions from "rocksolidjs/DialogActions";
import DialogContent from "rocksolidjs/DialogContent";
import DialogTitle from "rocksolidjs/DialogTitle";
export default function Example() {
const [open, setOpen] = createSignal(false);
let openButton!: HTMLButtonElement,
closeBtn!: HTMLButtonElement;
createEffect(() => {
if (open()) {
closeBtn.focus();
}
});
const handleDialogClose = () => {
setOpen(false);
openButton.focus();
};
return (
<>
<Button
ref={openButton}
onClick={() => setOpen(true)}
>
Open dialog
</Button>
<Dialog
open={open()}
aria-labelledby="welcome-dialog-title"
onClose={handleDialogClose}
class="max-w-md"
>
<DialogTitle id="welcome-dialog-title">
Welcome to the workspace
</DialogTitle>
<DialogContent>
Your workspace is ready. You can invite your team, create
projects, and start collaborating.
</DialogContent>
<DialogActions>
<Button
ref={closeBtn}
onClick={handleDialogClose}
>
Close
</Button>
</DialogActions>
</Dialog>
</>
);
}Alert dialog
Use role="alertdialog" for dialogs that require the user’s immediate
attention, such as destructive or irreversible actions. Use
aria-labelledby to associate the dialog with its DialogTitle.
import { createSignal, createEffect } from "solid-js";
import Button from "rocksolidjs/Button";
import Dialog from "rocksolidjs/Dialog";
import DialogActions from "rocksolidjs/DialogActions";
import DialogContent from "rocksolidjs/DialogContent";
import DialogTitle from "rocksolidjs/DialogTitle";
export default function Example() {
const [open, setOpen] = createSignal(false);
let openButton!: HTMLButtonElement,
cancelBtn!: HTMLButtonElement;
createEffect(() => {
if (open()) {
cancelBtn.focus();
}
});
const handleDialogClose = () => {
setOpen(false);
openButton.focus();
};
return (
<>
<Button
ref={openButton}
onClick={() => setOpen(true)}
>
Delete account
</Button>
<Dialog
open={open()}
role="alertdialog"
aria-labelledby="delete-account-title"
onClose={handleDialogClose}
class="max-w-md"
>
<DialogTitle id="delete-account-title">
Delete account?
</DialogTitle>
<DialogContent>
This action permanently deletes your account and all of its data.
You won't be able to undo this action.
</DialogContent>
<DialogActions>
<Button
ref={cancelBtn}
variant="outlined"
onClick={handleDialogClose}
>
Cancel
</Button>
<Button
color="error"
onClick={handleDialogClose}
>
Delete account
</Button>
</DialogActions>
</Dialog>
</>
);
}Fullscreen
Use the fullscreen prop when the dialog should occupy the available
viewport instead of appearing as a smaller modal.
import { createSignal } from "solid-js";
import Button from "rocksolidjs/Button";
import Dialog from "rocksolidjs/Dialog";
import DialogActions from "rocksolidjs/DialogActions";
import DialogContent from "rocksolidjs/DialogContent";
import DialogTitle from "rocksolidjs/DialogTitle";
export default function Example() {
const [open, setOpen] = createSignal(false);
return (
<>
<Button onClick={() => setOpen(true)}>View report</Button>
<Dialog
open={open()}
fullscreen
onClose={() => setOpen(false)}
>
<DialogTitle>Quarterly sales report</DialogTitle>
<DialogContent>
<p>
Review your sales performance for the current quarter.
</p>
<ul>
<li>Revenue increased by 18%.</li>
<li>New customers increased by 24%.</li>
<li>Customer retention improved by 6%.</li>
</ul>
</DialogContent>
<DialogActions>
<Button onClick={() => setOpen(false)}>Close</Button>
</DialogActions>
</Dialog>
</>
);
}Close Reasons
Use the onClose callback to respond when the dialog is requested to close.
The callback receives the event and a reason describing how the close was
triggered.
The reason can be one of:
escape— The user pressed the Escape key.backdrop— The user interacted with the backdrop.
import { createSignal } from "solid-js";
import Button from "rocksolidjs/Button";
import Dialog, { type DialogCloseReason } from "rocksolidjs/Dialog";
import DialogActions from "rocksolidjs/DialogActions";
import DialogContent from "rocksolidjs/DialogContent";
import DialogTitle from "rocksolidjs/DialogTitle";
import Typography from "rocksolidjs/Typography";
export default function Example() {
const [open, setOpen] = createSignal(false);
const [reason, setReason] = createSignal<string>();
const handleClose = (
_event: Event,
closeReason: DialogCloseReason,
) => {
setReason(closeReason);
setOpen(false);
};
return (
<div class="space-y-2 text-center">
<Button
onClick={() => setOpen(true)}
>
Open dialog
</Button>
{reason() && (
<Typography>
Dialog closed because of: <strong>{reason()}</strong>
</Typography>
)}
<Dialog
open={open()}
onClose={handleClose}
>
<DialogTitle>Unsaved changes</DialogTitle>
<DialogContent>
You have changes that haven't been saved. Are you sure you want to
leave this dialog?
</DialogContent>
<DialogActions>
<Button
onClick={() => setOpen(false)}
>
Keep editing
</Button>
<Button
onClick={() => setOpen(false)}
color="error"
>
Discard changes
</Button>
</DialogActions>
</Dialog>
</div>
);
}Customization
Use the class prop on each Dialog component to add custom styling.
import { createSignal } from "solid-js";
import Button from "rocksolidjs/Button";
import Dialog from "rocksolidjs/Dialog";
import DialogActions from "rocksolidjs/DialogActions";
import DialogContent from "rocksolidjs/DialogContent";
import DialogTitle from "rocksolidjs/DialogTitle";
import Divider from "rocksolidjs/Divider";
export default function Example() {
const [open, setOpen] = createSignal(false);
return (
<>
<Button onClick={() => setOpen(true)}>Show alert</Button>
<Dialog
open={open()}
class="max-w-xs rounded-2xl"
aria-labelledby="ios-dialog-title"
onClose={() => setOpen(false)}
>
<DialogTitle
id="ios-dialog-title"
class="text-center"
>
Allow Notifications?
</DialogTitle>
<DialogContent class="px-6 pb-5 text-center text-balance">
Notifications may include alerts, sounds, and icon badges.
</DialogContent>
<DialogActions class="flex gap-2">
<Button
variant="text"
class="flex-1"
onClick={() => setOpen(false)}
>
Don't Allow
</Button>
<Divider
orientation="vertical"
/>
<Button
variant="text"
class="font-semibold flex-1"
onClick={() => setOpen(false)}
>
Allow
</Button>
</DialogActions>
</Dialog>
</>
);
}Accessibility
- The dialog uses
role="dialog"by default. Userole="alertdialog"when the dialog requires the user’s immediate attention, such as a destructive confirmation. - The dialog should use
aria-labelledbyto reference theDialogTitle, providing an accessible name for the dialog. - The dialog uses
aria-modal="true"to indicate that content outside the dialog is not available while it is open. - When the dialog opens, ensure focus is moved to an appropriate element based on the dialog’s purpose and interaction requirements.
- When the dialog closes, focus should be restored to the element that triggered it.
- The
Dialogcomponent automatically traps focus within the dialog while it is open. - Give every dialog a clear and descriptive
DialogTitle. - Ensure the dialog can be closed using the Escape key when appropriate.
- Use clear labels for actions, especially for destructive or irreversible operations.
- When using a close button, ensure it has an accessible name.
API
Dialog
The Dialog component controls the modal container and provides support for controlled visibility, fullscreen layouts, custom styling, and close events.
| Prop | Type | Required | Default | Description |
|---|---|---|---|---|
| aria-labelledby | string |
No | — | Identifies the element that labels the dialog, typically the DialogTitle element. |
| children | JSXElement |
No | — | Content rendered inside the dialog. |
| class | string |
No | — | Custom CSS class applied to the dialog. |
| fullscreen | boolean |
No | false |
Controls whether the dialog is displayed in fullscreen mode. |
| open | boolean |
No | — | Controls whether the dialog is open. |
| onClose | (event: Event, reason: DialogCloseReason) => void |
No | — | Callback invoked when the dialog requests to close. The reason identifies how the close was triggered: escape when the user presses the Escape key, or backdrop when the user clicks the backdrop. |
| role | "dialog" | "alertdialog" |
No | "dialog" |
Defines the semantic role of the dialog. Use alertdialog when the dialog requires the user’s immediate attention. |
| slotProps | { backdrop?: object } |
No | — | Provides additional props for customizing individual dialog slots.
|
DialogTitle
DialogTitle provides the heading for a dialog.
| Prop | Type | Required | Default | Description |
|---|---|---|---|---|
| children | JSXElement |
No | — | Content rendered as the dialog title. |
| class | string |
No | — | Custom CSS class applied to the dialog title. |
DialogContent
DialogContent contains the primary content of the dialog.
| Prop | Type | Required | Default | Description |
|---|---|---|---|---|
| children | JSXElement |
No | — | Content rendered inside the dialog body. |
| class | string |
No | — | Custom CSS class applied to the dialog content. |
DialogActions
DialogActions contains actions such as buttons, links, or other controls
that appear at the bottom of the dialog.
| Prop | Type | Required | Default | Description |
|---|---|---|---|---|
| children | JSXElement |
No | — | Action elements rendered inside the dialog actions container. |
| class | string |
No | — | Custom CSS class applied to the dialog actions container. |