Alert dialog
Asks a question people must answer before going on, like confirming a delete.
Installation
The CLI installs the Radix or Base UI file to match your project, with what it builds on: button.
If your project doesn't have Wisty UI's theme yet, add it once with npx shadcn@latest add @wisty/cosmos. Until then, components keep shadcn's default look. Installation has the details.
When to use
Use it
- People confirm an action they can't easily undo, like deleting a record or discarding changes.
- A system problem stops the current task and people must acknowledge it, like a service that's down.
- A short yes or no question must be answered before going on.
Usage
import {
AlertDialog,
AlertDialogAction,
AlertDialogCancel,
AlertDialogContent,
AlertDialogDescription,
AlertDialogFooter,
AlertDialogHeader,
AlertDialogMedia,
AlertDialogTitle,
AlertDialogTrigger,
} from "@/components/ui/alert-dialog"AlertDialog
├── AlertDialogTrigger
└── AlertDialogContent
├── AlertDialogHeader
│ ├── AlertDialogMedia (optional icon)
│ ├── AlertDialogTitle
│ └── AlertDialogDescription
└── AlertDialogFooter
├── AlertDialogCancel
└── AlertDialogActionStyle the trigger with className={buttonVariants()} from Button, as the examples do.
AlertDialogAction and AlertDialogCancel close the dialog as soon as they're clicked. To keep it open while the action runs, like a delete that waits for the server, control open and put a Button in the footer in place of the Action:
const [open, setOpen] = useState(false)
async function remove() {
await deleteAccount()
setOpen(false)
}
return (
<AlertDialog open={open} onOpenChange={setOpen}>
{/* trigger and header as in the examples, then in the footer: */}
{/* <Button variant="destructive" onClick={remove}>Delete</Button> */}
</AlertDialog>
)Examples
Header colors
The plain, success and info headers, set with `variant` on `AlertDialogContent`, each with Cancel and a brand action.
Warning
A service that's down, with `variant="warning"` and a single `AlertDialogCancel` as the Okay button.
Small with media
A short question with its buttons side by side, set with `size="sm"`, and an icon in `AlertDialogMedia`.
API reference
| Part | Built on |
|---|---|
AlertDialog | Radix AlertDialog.Root (opens in a new tab) |
AlertDialogTrigger | Radix AlertDialog.Trigger (opens in a new tab) |
AlertDialogPortal | Radix AlertDialog.Portal (opens in a new tab) |
AlertDialogOverlay | Radix AlertDialog.Overlay (opens in a new tab) |
AlertDialogContent | Radix AlertDialog.Content (opens in a new tab) |
AlertDialogHeader | <div> (opens in a new tab) |
AlertDialogFooter | <div> (opens in a new tab) |
AlertDialogMedia | <div> (opens in a new tab) |
AlertDialogTitle | Radix AlertDialog.Title (opens in a new tab) |
AlertDialogDescription | Radix AlertDialog.Description (opens in a new tab) |
AlertDialogAction | Radix AlertDialog.Action (opens in a new tab) |
AlertDialogCancel | Radix AlertDialog.Cancel (opens in a new tab) |
AlertDialogContent
| Prop | Type | Default |
|---|---|---|
size | "default" | "sm" | "default" |
variant | "default" | "destructive" | "warning" | "success" | "info" | "default" |
AlertDialogAction
| Prop | Type | Default |
|---|---|---|
variant | "default" | "outline" | "secondary" | "ghost" | "destructive" | "link" | "outline-brand" | "destructive-text" | "success" | "inverse" | "default" |
size | "default" | "xs" | "sm" | "lg" | "icon" | "icon-xs" | "icon-sm" | "icon-lg" | "default" |
AlertDialogCancel
| Prop | Type | Default |
|---|---|---|
variant | "default" | "outline" | "secondary" | "ghost" | "destructive" | "link" | "outline-brand" | "destructive-text" | "success" | "inverse" | "outline" |
size | "default" | "xs" | "sm" | "lg" | "icon" | "icon-xs" | "icon-sm" | "icon-lg" | "default" |
SLDS mapping
AlertDialogContent is slds-modal slds-modal_prompt, and AlertDialogOverlay is slds-backdrop, as Dialog's. AlertDialogHeader is slds-modal__header, themed by variant, and AlertDialogTitle is its slds-text-heading_medium heading. AlertDialogDescription is the prompt's message in slds-modal__content, on the box's own background under the themed header. A link in it takes the link color, underlined so it doesn't rely on color alone. AlertDialogFooter is slds-modal__footer slds-theme_default. AlertDialogMedia has no SLDS counterpart: it's Empty's gray icon box. The title's alignment, the footer's rule and its button alignment follow each theme's prompt hooks.
Known gaps:
- SLDS's striped header texture (
slds-theme_alert-texture) isn't in the SLDS 2 stylesheet, so it isn't here either. - Icons are lucide's, not SLDS's utility icons.
| Prop | Value | SLDS | Notes |
|---|---|---|---|
size | default | slds-modal slds-modal_prompt | 40rem at most, as dialog. |
size | sm | slds-modal slds-modal_prompt | 20rem, SLDS's smallest modal width, with the footer buttons side by side. SLDS has no small prompt. |
variant | default (added) | slds-modal__header | The header on the box's background. |
variant | destructive (added) | slds-modal__header slds-theme_error | |
variant | warning (added) | slds-modal__header slds-theme_warning | |
variant | success (added) | slds-modal__header slds-theme_success | |
variant | info (added) | slds-modal__header slds-theme_info |
Keyboard interactions
| Keys | Action |
|---|---|
| Escape | Closes the dialog and returns focus to the trigger. With a combobox's list open inside, closes only the list; press again. |
| Tab, Shift+Tab | Moves between the dialog's controls and stays inside it. |
A Command's search field isn't an open list, so Escape there closes the dialog.
Accessibility
- Always include an
AlertDialogTitleand anAlertDialogDescription. They name and describe the dialog, so screen readers read the question when it opens. - Always include an
AlertDialogCancel, first in the footer, even when it's the only button, like an Okay. Focus moves to it on open; without one, focus can stay on the trigger behind the dialog. - Clicking outside doesn't close the dialog. People choose a button or press Escape.
Motion
- The backdrop and the box fade in, the box faster, as Dialog's do, in every theme. Nothing moves, so the fades stay on with reduced motion.
Responsive behavior
- From 48rem (768px) wide, the dialog is half the screen wide, between 20rem and 40rem. Below it, it fills the screen less 2rem on each side.
size="sm"stays at 20rem or less. - The title wraps and long words break. Footer buttons wrap onto a second line when they don't fit; in
size="sm"they share the row in two equal columns.
Performance
- The content renders in a portal at
document.body, only while open, so styles scoped to an ancestor don't reach it.
Rules
- For a delete or another destructive action, pass
variant="destructive"to bothAlertDialogContentandAlertDialogAction. - Use
variant="warning"for a system problem people must acknowledge, with a single Cancel such as "Okay", as the Warning example shows. - Don't restyle the header, corners or colors with utility classes. They come from the theme tokens.
Related
- DialogOpens a window over the page for a short task or a message that needs an answer.
- SonnerShows brief, non-blocking messages, like a saved record or a failed request.
- AlertTells people about part of the page, with an icon, a title and an action.
- SheetSlides a panel in from the edge of the screen for a task beside the page.