Alert Dialog
A modal dialog that interrupts the user with important content and expects a response.
Are you absolutely sure?
This action cannot be undone. This will permanently delete your account and remove your data from our servers.
AlertDialog is a Dialog for irreversible decisions: deleting an account, discarding unsaved changes, cancelling an operation in progress. It is built on the Dialog parts and differs from Dialog in four ways:
- The panel has
role="alertdialog". - No × button in the corner.
- Escape and a click on the backdrop do not close it: the user has to choose Cancel or Action.
AlertDialogCancelandAlertDialogActionare ready-made buttons that close the dialog. Cancel receives focus when the dialog opens.
Use it only for real destructive decisions; forms and edits belong in a regular Dialog.
Idiomatic composition:
- AlertDialogTitle asks the question ("Are you absolutely sure?"). Phrasing it as a question is recommended.
- AlertDialogDescription explains the consequences ("This action cannot be undone. This will permanently delete…"). Always state that the action is irreversible.
- AlertDialogCancel is the neutral button (outline), typically on the left. Closes without acting.
- AlertDialogAction is the primary (or destructive) button, on the right. It closes the dialog; attach your own handler to run the operation.
Installation
$ bext ui add alert-dialog
Usage
Anatomy
<AlertDialog>
├── <AlertDialogTrigger for="alert-id"> // data-ui="open"
│ └── <Button>Delete account</Button>
└── <AlertDialogContent id="alert-id"> // role="alertdialog"
├── <AlertDialogHeader>
│ ├── <AlertDialogTitle>...</AlertDialogTitle>
│ └── <AlertDialogDescription>...</AlertDialogDescription>
└── <AlertDialogFooter>
├── <AlertDialogCancel>Cancel</AlertDialogCancel>
└── <AlertDialogAction>Delete</AlertDialogAction>API Reference
AlertDialog
| Prop | Type | Default | Description |
|---|---|---|---|
| children | ReactNode | — | The trigger and the content. Renders no element of its own. |
AlertDialogTrigger
| Prop | Type | Default | Description |
|---|---|---|---|
| for | string | — | Matches the id of the AlertDialogContent to open. |
| children | ReactNode | — | Button that opens the dialog. |
| className | string | — | Extra classes on the wrapping (inline-flex). |
AlertDialogContent
| Prop | Type | Default | Description |
|---|---|---|---|
| id | string | — | Matches AlertDialogTrigger.for. |
| ariaLabel | string | — | Accessible name (aria-label) when there is no AlertDialogTitle. With a title, leave it out. |
| className | string | — | Extra classes on the centered panel (role="alertdialog", aria-modal="true", max-w-lg). The panel has no corner close button. |
AlertDialogHeader
| Prop | Type | Default | Description |
|---|---|---|---|
| className | string | — | flex-col space-y-1.5 container for the title and description. |
AlertDialogTitle
| Prop | Type | Default | Description |
|---|---|---|---|
| className | string | — | <h2> text-lg font-semibold. Phrasing it as a question is recommended. |
AlertDialogDescription
| Prop | Type | Default | Description |
|---|---|---|---|
| className | string | — | <p> text-sm muted-foreground. Always state that the action is irreversible. |
AlertDialogFooter
| Prop | Type | Default | Description |
|---|---|---|---|
| className | string | — | flex-col-reverse on mobile → flex-row at sm+, justify-end. Cancel on the left, Action on the right. |
AlertDialogCancel
| Prop | Type | Default | Description |
|---|---|---|---|
| children | ReactNode | — | Label of the neutral button (typically "Cancel" or "Never mind"). Rendered as Button variant="outline" inside a data-ui="close" data-ui-cancel wrapper. It receives focus when the dialog opens. |
| className | string | — | Extra classes on the button. |
AlertDialogAction
| Prop | Type | Default | Description |
|---|---|---|---|
| children | ReactNode | — | Label of the confirm button ("Continue", "Delete account"). Rendered as Button variant="default" inside a data-ui="close" wrapper. It has no variant prop: for a red button, use <DialogClose><Button variant="destructive"> instead (see the first example). |
| className | string | — | Extra classes on the button. |
Data Attributes
Attributes you can target in custom CSS to override the style for each state.
| Attribute | On | Values | Description |
|---|---|---|---|
| data-overlay | AlertDialogContent (outer element) | — | Marks the overlay. The island toggles its hidden attribute. |
| data-ui="open" | AlertDialogTrigger | data-target="#id" | Clicking opens the overlay and locks page scroll. |
| data-ui="close" | Cancel + Action | — | Clicking closes the overlay and returns focus to the trigger. |
| data-ui-cancel | AlertDialogCancel | present | Marks the button that receives focus on open. |
| data-ui="overlay-bg" | backdrop | — | Present, but a click on it is ignored because the panel is an alertdialog. |
| data-state | AlertDialogTrigger | "open" | "closed" | Set by the island, together with aria-haspopup="dialog", aria-expanded and aria-controls on the button inside. |
Keyboard
| Key | Action |
|---|---|
| Enter / Space | On the trigger: opens the dialog and focuses Cancel. Inside: activates the focused button. |
| Tab / Shift+Tab | Moves between Cancel and Action and wraps around. Focus cannot leave the dialog. |
| Escape | Does nothing: the dialog closes only from Cancel or Action. |
Accessibility
AlertDialogContent sets role="alertdialog" and aria-modal="true" on the panel. The island points aria-labelledby at the AlertDialogTitle and aria-describedby at the AlertDialogDescription, so both are announced when the dialog opens.
Focus: on open, focus moves to the Cancel button, the least destructive action (or to the first focusable element when there is no AlertDialogCancel). Tab and Shift+Tab are trapped inside. On close, focus returns to the trigger.
Dismissal: Escape and a backdrop click are ignored. Always render a Cancel button, otherwise the user has no way out. Run the destructive operation only from the Action button.
Use sparingly: every AlertDialog interrupts the flow. Reserve it for real destructive decisions (permanent deletion, cancelling a batch, exiting without saving). For routine confirmation, a regular Dialog plus a confirmation toast after the action is enough.
Examples
Destructive action (red)
Delete 42 files?
This permanently removes the selected files. They cannot be recovered.
Without description
Discard unsaved changes?
Edit this component live in the bext playground. The PRISM + signals version is the bext-native idiom: fine-grained reactivity, no virtual DOM.
On This Page