Components / Alert Dialog
Alert Dialog
A blocking confirmation before a destructive or irreversible action: deleting a post, disconnecting an account, discarding an edit, approving a spend change. The user must explicitly cancel or confirm. If the surface asks a question and the answer commits something, it is this — not a Dialog wearing two buttons.
import { AlertDialog, AlertDialogAction, AlertDialogBody, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogMedia, AlertDialogTitle, AlertDialogTrigger } from '@layers/ui/alert-dialog'Rendered stock
House rules
- Reserve it for confirmations. Anything with fields or richer content is a Dialog.
- The markup is fixed: AlertDialogHeader (title, then description), an optional AlertDialogBody, then AlertDialogFooter. Nothing else is a direct child of AlertDialogContent — a bare <p>, a hand-rolled well or a naked Field between the header and the footer is the drift this contract exists to end.
- The title asks the question ("Discard changes?", "Delete this catalog?"), and the description answers what happens if they say yes. Never a title that narrates the click ("Confirm to remove slide").
- AlertDialogDescription is text-base (14px) in full-strength popover ink — NOT the muted 12px a DialogDescription gets. A Dialog description subtitles the content beneath it; an AlertDialog has nothing beneath it, so that sentence IS the decision. Do not restate it at a smaller size in the body.
- AlertDialogBody carries the specifics the decision hangs on — the record being deleted, the reason it was flagged, the one field the confirm collects. It is a Card, so the block reads as its own plane inside the popup. Never a bare <p>, never a rounded-md border bg-secondary well, and never a padding utility: AlertDialogContent already owns p-6, so a p-6 body strands the text in 48px of nothing.
- A confirmation has no X. AlertDialog offers exactly two exits, Cancel and the action, and that is the point — reaching for Dialog to get a close button turns a decision into something dismissable.
- AlertDialogMedia takes tone="destructive" for the red glyph; never hand-write the destructive tint at the call site.
- AlertDialogAction is a plain Button and does not close the dialog by itself; drive open with controlled state and close after the action settles.
- No optimistic destructive actions: the confirm button disables and shows a spinner while the mutation is pending (loading={m.isPending}).
- A teardown confirm inherits the verb — AlertDialogAction takes variant="destructive" when the action deletes, removes, revokes or discards.
- AlertDialogCancel renders the outline Button and closes the dialog; keep it first in the footer. It is outline by default — do not pass variant="outline" at the call site.
- AlertDialogAction and AlertDialogCancel default to size="lg" (40px) — the wrapper owns the footer-button size so AlertDialogs cannot drift. Do not pass size at the call site.