AlertDialog
Blocking confirmation dialog for destructive or critical actions. Built on Base UI's alert-dialog primitive with role="alertdialog", focus trap, and explicit-action-only dismissal — the user must choose Confirm or Cancel.
Playground
Installation
pnpm add @tessinaui/uiUsage
import {
AlertDialog,
AlertDialogTrigger,
AlertDialogContent,
AlertDialogHeader,
AlertDialogTitle,
AlertDialogDescription,
AlertDialogBody,
AlertDialogFooter,
AlertDialogAction,
AlertDialogCancel,
} from "@tessinaui/ui";<AlertDialog intent="error">
<AlertDialogTrigger render={<Button intent="error">Delete</Button>} />
<AlertDialogContent>
<AlertDialogHeader>
<AlertDialogTitle>Delete this project?</AlertDialogTitle>
<AlertDialogDescription>
This action cannot be undone.
</AlertDialogDescription>
</AlertDialogHeader>
<AlertDialogFooter>
<AlertDialogCancel>Cancel</AlertDialogCancel>
<AlertDialogAction>Delete</AlertDialogAction>
</AlertDialogFooter>
</AlertDialogContent>
</AlertDialog>Examples
Default
A destructive confirmation with the error intent and an icon trigger.
Intents
intent drives the header icon and the default action-button colour — error, warning, success, and info.
Sizes
Four max-widths — sm, md, lg, and xl — to fit the message length.
Footer layout
AlertDialogFooter lays buttons out as an end-aligned row or a full-width stacked column.
Intent border
Opt in to a colour-matched popup border with showIntentBorder.
Loading
AlertDialogSkeleton mirrors the popup shape while content loads.
When to use AlertDialog vs. Modal vs. Alert
| Use AlertDialog when… | Use Modal when… | Use Alert when… |
|---|---|---|
| The user must explicitly confirm or cancel | The dialog holds form fields, lists, or rich content | You only need to inform the user inline |
| The action is destructive, irreversible, or critical | Outside-click and Escape are acceptable dismissals | The message can be ignored without consequence |
You need stronger accessibility semantics (role="alertdialog") | The decision isn't critical | The notification appears in the page flow, not as an overlay |
Anatomy
<AlertDialog>
<AlertDialogTrigger>…</AlertDialogTrigger>
<AlertDialogContent>
<AlertDialogHeader>
<AlertDialogTitle />
<AlertDialogDescription />
</AlertDialogHeader>
<AlertDialogBody /> {/* optional */}
<AlertDialogFooter>
<AlertDialogCancel />
<AlertDialogAction />
</AlertDialogFooter>
</AlertDialogContent>
</AlertDialog>AlertDialogHeader automatically renders the icon for the current intent (or your custom icon). AlertDialogAction is intent-aware — it inherits the dialog's intent so destructive confirmations are coloured correctly without extra props.
Size
| Size | Max width |
|---|---|
"sm" | max-w-sm (24rem) |
"md" (default) | max-w-md (28rem) |
"lg" | max-w-lg (32rem) |
"xl" | max-w-xl (36rem) |
Intent
intent drives the header icon (auto) and the default colour of AlertDialogAction. The popup border stays neutral by default — opt in to a coloured border with showIntentBorder when the surrounding context doesn't already convey urgency.
| Value | Header icon | Default action button | Border with showIntentBorder |
|---|---|---|---|
"none" (default) | Info | bg-primary | border-border |
"error" | CircleX | bg-error | border-error |
"warning" | TriangleAlert | bg-warning | border-warning |
"success" | CircleCheck | bg-success | border-success |
"info" | Info | bg-info | border-info |
Rounded
| Value | CSS |
|---|---|
"none" | rounded-none |
"sm" | rounded-lg |
"md" (default) | rounded-xl |
"lg" | rounded-2xl |
"full" | rounded-3xl |
Footer layout
AlertDialogFooter accepts layout:
"row"(default) — horizontal, end-aligned. Standard desktop pattern."stacked"— full-width buttons stacked vertically. iOS / mobile style.
<AlertDialogFooter layout="stacked">
<AlertDialogAction>Power off</AlertDialogAction>
<AlertDialogCancel>Cancel</AlertDialogCancel>
</AlertDialogFooter>When layout="stacked", place AlertDialogAction first — flex-col-reverse puts it on top so the destructive action sits closest to the title.
Dismissal behaviour
Unlike Modal, the alert dialog cannot be dismissed by:
- Clicking outside the popup
- Pressing Escape
The user must choose AlertDialogAction, AlertDialogCancel, or your own AlertDialogClose. This is the W3C-recommended pattern for role="alertdialog".
Controlled
const [open, setOpen] = React.useState(false);
<AlertDialog open={open} onOpenChange={setOpen}>
…
</AlertDialog>Custom action via AlertDialogClose
When you need full control over the button (e.g., async confirmation, loading state), use AlertDialogClose directly with render:
<AlertDialogClose
render={
<Button onClick={async () => {
await deleteProject();
// dialog closes automatically after the click handler resolves
}}>
Delete forever
</Button>
}
/>Accessibility
- Renders with
role="alertdialog"so screen readers treat it as a critical interruption. AlertDialogTitleis wired toaria-labelledby,AlertDialogDescriptiontoaria-describedby.- Focus traps inside the popup. On open, focus moves to the first focusable element (typically
AlertDialogCancel). - On close, focus returns to the trigger.
- The popup is not dismissible by outside click or Escape — both gestures are intentionally swallowed.
- Use
intent="error"for destructive confirmations; the semantic colour, header icon, and action button intent all update so assistive tech and sighted users get the same signal.
RTL
Pass dir="rtl" to the root. The header icon, title, footer button order, and stacked layout all follow the reading direction.
<AlertDialog dir="rtl" intent="error">
<AlertDialogTrigger render={<Button intent="error">حذف</Button>} />
<AlertDialogContent>
<AlertDialogHeader>
<AlertDialogTitle>هل أنت متأكد من الحذف؟</AlertDialogTitle>
<AlertDialogDescription>لا يمكن التراجع عن هذا الإجراء.</AlertDialogDescription>
</AlertDialogHeader>
<AlertDialogFooter>
<AlertDialogCancel>إلغاء</AlertDialogCancel>
<AlertDialogAction>حذف</AlertDialogAction>
</AlertDialogFooter>
</AlertDialogContent>
</AlertDialog>API Reference
AlertDialog (root)
| Prop | Type | Default | Description |
|---|---|---|---|
size | "sm" | "md" | "lg" | "xl" | "md" | Max-width of the popup |
rounded | "none" | "sm" | "md" | "lg" | "full" | "md" | Corner radius — also inherited by AlertDialogAction and AlertDialogCancel |
intent | "none" | "error" | "warning" | "success" | "info" | "none" | Header icon and default action-button intent |
showIntentBorder | boolean | false | When true, the popup border picks up the intent colour. Opt-in — neutral border by default |
dir | "ltr" | "rtl" | "ltr" | Reading direction |
open | boolean | — | Controlled open state |
defaultOpen | boolean | false | Uncontrolled initial state |
onOpenChange | (open, event) => void | — | Fired when open state changes |
AlertDialogContent
Inherits size, rounded, intent, and dir from the root. Override any of them to scope the popup independently.
AlertDialogHeader
| Prop | Type | Default | Description |
|---|---|---|---|
icon | ReactNode | intent icon | Custom leading icon next to the title |
showIcon | boolean | true | Render an icon — set to false for icon-less alerts |
AlertDialogFooter
| Prop | Type | Default | Description |
|---|---|---|---|
layout | "row" | "stacked" | "row" | Horizontal end-aligned, or full-width stacked vertically |
AlertDialogAction, AlertDialogCancel
Both render a Button. Pass any Button prop (size, rounded, loading, leadingIcon, etc.). Both auto-close the dialog on click.
AlertDialogActiondefaults tovariant="primary"and inherits the dialog'sintent.AlertDialogCanceldefaults tovariant="outline"andintent="none".
AlertDialogTrigger, AlertDialogClose
Render a <button>. Use render={<CustomElement />} to swap in a Button or any element. Standard Base UI render-prop pattern.
Sub-components
AlertDialogTitle, AlertDialogDescription, AlertDialogBody, AlertDialogBackdrop — all accept className and any HTML props.
Notes
- Built on
@base-ui/react/alert-dialog, with W3Crole="alertdialog"semantics. - The popup uses Base UI's
data-[starting-style]anddata-[ending-style]attributes for entry/exit animation. - The header icon background tints automatically per intent (
bg-error-lightetc.) for a soft callout.
Alert
Contextual feedback messages for user actions or system events. Four visual variants (solid, soft, outline, ghost), five intents, three sizes, six rounded options, optional close button, actions, and RTL support.
Area Chart
Token-driven area chart built on Recharts v3 with gradient fills, stacking, single and multi-series support, and full light/dark theming via chart tokens.