Alert dialog
FreeThe Dialog surface for a decision that cannot be undone: no close button, no outside dismiss, focus starting on the safe choice.
pnpm dlx shadcn@latest add https://caliperui.site/r/alert-dialog.jsonWhen to use #
Use it for
- Deleting a workspace, revoking a key, discarding unsaved work.
- Anything where the next click is permanent.
Skip it when
- Information or forms; use a dialog.
- Anything you can undo; do it and offer Undo in a toast.
Decisions #
Why it is built this way, so you know what to keep when you change your copy.
Behaviour
- Focus starts on Cancel
- The least destructive choice is the one an accidental Enter lands on. Escape also cancels.
- An outside click does nothing
- A decision this large should not be dismissed by missing a button. Only Cancel and Escape close it.
Usage
- The action names what it does
- “Delete workspace” instead of “OK”, so the last thing read before the click is the consequence.
Installation #
pnpm dlx shadcn@latest add https://caliperui.site/r/alert-dialog.json
Adds its 5 files to components/ui/, each with its own stylesheet, and installs their packages. No account needed. The first part also adds Caliper UI’s tokens; import them once as in Installation.
Usage #
This is the code behind the preview above. It is built from AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogTitle and AlertDialogTrigger.
import { useState } from "react" import { AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogTitle, AlertDialogTrigger } from "@/components/ui/alert-dialog" import { Button } from "@/components/ui/button" export function AlertDialogDemo() { const [result, setResult] = useState(""); return ( <div className="grid justify-items-center gap-3"> <AlertDialog> <AlertDialogTrigger asChild> <Button variant="destructive">Delete workspace…</Button> </AlertDialogTrigger> <AlertDialogContent> <AlertDialogHeader> <AlertDialogTitle>Delete Forma Studio?</AlertDialogTitle> <AlertDialogDescription>This removes 14 projects and 212 files for everyone in the workspace. You cannot undo it.</AlertDialogDescription> </AlertDialogHeader> <AlertDialogFooter> <AlertDialogCancel onClick={() => setResult("Kept. Nothing was deleted.")}>Keep project</AlertDialogCancel> <AlertDialogAction onClick={() => setResult("Workspace deleted (example only).")}>Delete workspace</AlertDialogAction> </AlertDialogFooter> </AlertDialogContent> </AlertDialog> <p role="status" className="min-h-5 text-sm text-muted-foreground">{result}</p> </div> ); }
API reference #
AlertDialog
component
No props of its own; it accepts the native props of its root element.
AlertDialogAction
component
Also accepts the native props of its root element and a ref.
AlertDialogCancel
component
Also accepts the native props of its root element and a ref.
AlertDialogContent
component
No props of its own; it accepts the native props of its root element.
AlertDialogDescription
component
No props of its own; it accepts the native props of its root element.
AlertDialogHeader
component
No props of its own; it accepts the native props of its root element.
AlertDialogTitle
component
No props of its own; it accepts the native props of its root element.
AlertDialogTrigger
component
No props of its own; it accepts the native props of its root element.
Accessibility #
It exposes alertdialog semantics.
Keyboard and focus handling comes from Radix dialog: arrow keys move through items, Enter and Space select, and Escape closes and returns focus.
Motion #
It declares no animation in its component source. Any transition comes from its stylesheet, which uses the duration tokens that collapse to instant under prefers-reduced-motion.