DocumentationComponentsTheme CreatorGitHub
Theme CreatorGitHubIntroduction
InstallationUsageTheming
ComponentsAccordionAction SheetAlertAlertDialogArea ChartAspectRatioAvatarBadgeBannerBar ChartBottom NavBreadcrumbButtonButtonGroupCalendarCardCarouselChartChatBubbleChatBubbleNewCheckboxChipCoachMarkCodeBlockCollapsibleColor PickerComboboxCommandContainerContextMenuDate PickerDividerDrawerDropdown MenuEmptyStateFABFieldFieldsetFile UploadFlexFormGridHoverCardIconButtonLabelLine ChartLinkMenubarMeterModalNavigation MenuNumberFieldOTP InputPaginationPickerPie ChartPopoverProgressPromptInputRadar ChartRadial ChartRadioRatingScroll AreaSearchSegmentedControlSelectShortcutSidebarSkeletonSliderCircularSliderMediaTrimmerSpacerSpinnerSplit ButtonStackStatusStepperSurfaceSwitchTableTabsTextareaTime PickerToastToggleButtonToggleGroupTokenizerToolbarTooltipTop Header DesktopTop Header Mobile
Contributing
Components

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/ui

Usage

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.

Destructive vs non-destructive

Intent decides more than colour: a destructive dialog focuses Cancel on open, per the APG rule to focus the least destructive action when undoing is impossible. A non-destructive one focuses the confirm instead.

Async confirm

Set busy while the mutation runs. The dialog stays open, the action shows a spinner, both buttons go inert, and Escape is vetoed — without the key ever being disabled.

Loading

AlertDialogSkeleton mirrors the popup shape while content loads.

Accessibility

Pattern: WAI-ARIA APG alertdialog.

  • The popup carries role="alertdialog" and aria-modal="true", is named by AlertDialogTitle and described by AlertDialogDescription. Rendering the description is not optional — Base UI wires aria-describedby from that part, so omitting it silently drops an attribute the pattern requires.
  • Initial focus defaults to Cancel for intent="error" / "warning" and to the action otherwise; override with initialFocus on AlertDialogContent. The surveyed systems split 4–4 on the general default, so it is explicit here rather than inherited from DOM order.
  • Escape closes, and must. Nine of eleven surveyed systems require it, and Spectrum defines it as equivalent to choosing Cancel. To hold the dialog open during an in-flight action use busy, which vetoes the close in the handler — never disable the key.
  • Outside clicks never dismiss. Base UI forces that for the alertdialog role; there is no prop to re-enable it.
  • While busy, both buttons are aria-disabled rather than disabled, so they stay in the tab sequence instead of vanishing mid-flight.
  • Focus returns to the trigger on close. When the confirmed action destroys the trigger — deleting the row that opened the dialog — pass finalFocus so focus lands on a real element rather than body.

AT matrix: VoiceOver + Safari — not yet run for this component. NVDA and JAWS UNTESTED (no Windows host, QA §5.6). The badge is beta for that reason, not because the API is unsettled.

When to use AlertDialog vs. Modal vs. Alert

Use AlertDialog when…Use Modal when…Use Alert when…
The user must explicitly confirm or cancelThe dialog holds form fields, lists, or rich contentYou only need to inform the user inline
The action is destructive, irreversible, or criticalOutside-click and Escape are acceptable dismissalsThe message can be ignored without consequence
You need stronger accessibility semantics (role="alertdialog")The decision isn't criticalThe 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

SizeMax 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.

ValueHeader iconDefault action buttonBorder with showIntentBorder
"none" (default)Infobg-primaryborder-border
"error"CircleXbg-errorborder-error
"warning"TriangleAlertbg-warningborder-warning
"success"CircleCheckbg-successborder-success
"info"Infobg-infoborder-info

Rounded

ValueCSS
"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.
  • AlertDialogTitle is wired to aria-labelledby, AlertDialogDescription to aria-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)

PropTypeDefaultDescription
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
showIntentBorderbooleanfalseWhen true, the popup border picks up the intent colour. Opt-in — neutral border by default
dir"ltr" | "rtl""ltr"Reading direction
openboolean—Controlled open state
defaultOpenbooleanfalseUncontrolled 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

PropTypeDefaultDescription
iconReactNodeintent iconCustom leading icon next to the title
showIconbooleantrueRender an icon — set to false for icon-less alerts

AlertDialogFooter

PropTypeDefaultDescription
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.

  • AlertDialogAction defaults to variant="primary" and inherits the dialog's intent.
  • AlertDialogCancel defaults to variant="outline" and intent="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 W3C role="alertdialog" semantics.
  • The popup uses Base UI's data-[starting-style] and data-[ending-style] attributes for entry/exit animation.
  • The header icon background tints automatically per intent (bg-error-light etc.) for a soft callout.
AlertArea Chart

On this page

PlaygroundInstallationUsageExamplesDefaultIntentsSizesFooter layoutIntent borderDestructive vs non-destructiveAsync confirmLoadingAccessibilityWhen to use AlertDialog vs. Modal vs. AlertAnatomySizeIntentRoundedFooter layoutDismissal behaviourControlledCustom action via AlertDialogCloseAccessibilityRTLAPI ReferenceAlertDialog (root)AlertDialogContentAlertDialogHeaderAlertDialogFooterAlertDialogAction, AlertDialogCancelAlertDialogTrigger, AlertDialogCloseSub-componentsNotes