Components
AlertDialog
Confirmation for an action that cannot be undone. It is not a Dialog with a flag — it is a different contract, with the safe answer in the first focus position and no way to dismiss it by clicking the scrim.
Examples
import {
AlertDialog,
AlertDialogAction,
AlertDialogCancel,
AlertDialogContent,
AlertDialogDescription,
AlertDialogFooter,
AlertDialogTitle,
AlertDialogTrigger,
} from "@luc/ui";A decision, not a page
Two shapes: a destructive confirm that defaults to danger, and an important-but-reversible confirm that takes the primary button. Escape still closes; a stray click does not.
<AlertDialog>
<AlertDialogTrigger asChild><Button variant="danger">Delete dataset</Button></AlertDialogTrigger>
<AlertDialogContent>…</AlertDialogContent>
</AlertDialog>When the confirmation needs input
A field inside the dialog is fine — it is still one decision, and the action button carries the verb.
<AlertDialog>
<AlertDialogTrigger asChild>
<Button variant="outline">Rename workspace</Button>
</AlertDialogTrigger>
<AlertDialogContent>
<AlertDialogTitle>Rename workspace</AlertDialogTitle>
<AlertDialogDescription>Links keep working; the slug changes immediately.</AlertDialogDescription>
<Input defaultValue="research" aria-label="Workspace slug" />
<AlertDialogFooter>
<AlertDialogCancel>Cancel</AlertDialogCancel>
<AlertDialogAction tone="primary">Rename</AlertDialogAction>
</AlertDialogFooter>
</AlertDialogContent>
</AlertDialog>When to use it
The test is reversibility. If the action can be undone in place, use a button and a toast instead; the dialog is for the case where there is nothing to undo.
Do
- Name the action (“Delete dataset”), never “OK”.
- Say what is lost and whether it can be undone.
- Reserve it for a decision that cannot be reverted in place.
Don't
- Use it for a confirmation that could be a Button with an undo.
- Stack two alert dialogs — one decision per moment.
- Put an irreversible action in the first focus position.
API
| Prop | Type | Default | Notes |
|---|---|---|---|
AlertDialog width | "sm" | "md" | "sm" | A confirmation is a decision, not a page. |
AlertDialogAction tone | "danger" | "primary" | "danger" | The safe reading of a confirmation is a destructive one. |
AlertDialogAction / Cancel | Radix Action / Cancel | — | They close the dialog; the work stays in your handler. |
Dismissal | Escape only | — | Radix removes outside-click dismissal from the contract entirely. |
Usage
import { AlertDialog, AlertDialogTrigger, AlertDialogContent, AlertDialogTitle, AlertDialogDescription, AlertDialogAction, AlertDialogCancel } from "@luc/ui";<AlertDialog>
<AlertDialogTrigger asChild>
<Button variant="danger">Delete dataset</Button>
</AlertDialogTrigger>
<AlertDialogContent>
<AlertDialogTitle>Delete this dataset?</AlertDialogTitle>
<AlertDialogDescription>The rows and their exports go with it.</AlertDialogDescription>
<AlertDialogCancel>Keep it</AlertDialogCancel>
<AlertDialogAction>Delete</AlertDialogAction>
</AlertDialogContent>
</AlertDialog>Guidelines
Do
- Reserve it for a decision the reader cannot undo from the same screen, and name the object in the title rather than asking a generic “Are you sure?”.
- Put the safe choice first: `AlertDialogCancel` is the default focus target, so Enter dismisses instead of confirming.
Don't
- Use it for information or for a form; an alert dialog has no cancel-on-outside-click and no free-form content contract.
Accessibility
It is a modal dialog with `role="alertdialog"`, so the title and description are announced when it opens. Focus moves to the cancel action, Escape dismisses, and focus returns to the trigger.
Related