Tessina UI
Tessina UI
GitHubIntroduction
InstallationUsageTheming
Components
ButtonIconButtonLinkSpinnerBadgeAvatarStatusChipShortcutSkeletonSurfaceProgressMeterRating
LabelFieldFieldsetCheckboxRadioSwitchSliderSelectComboboxSearchTextareaNumberFieldDate PickerTime PickerOTP InputFile UploadCalendar
AlertBannerToastTooltip
TabsAccordionCollapsibleBreadcrumbPaginationStepperSegmentedControlButtonGroupToggleButtonToggleGroupToolbarNavigation MenuMenubarBottom NavSidebar
Split ButtonFABDropdown MenuContextMenuCommandPopoverHoverCard
ContainerStackFlexGridAspectRatioSpacerCardCarouselDividerScroll Area
Table
ChatBubblePromptInputCodeBlock
ModalAlertDialogDrawerAction SheetTop Header MobileTop Header DesktopEmptyStateForm
Contributing
ComponentsSurfaces

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>

Showcase

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 — the same primitive used by Radix and shadcn for the same component, 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.

Modal

An accessible dialog overlay built on Base UI. Compound component pattern with Header, Body, Footer, Title, Description, and Close. Five sizes. Five corner-rounding options. LTR and RTL support.

Drawer

An accessible slide-in panel built on Base UI Dialog. Compound component pattern with Header, Body, Footer, Title, and Description. Four sides (right, left, top, bottom). Five sizes. Five corner-rounding options. Auto-stacking footer for sheets. LTR and RTL support.

On this page

PlaygroundInstallationUsageShowcaseWhen to use AlertDialog vs. Modal vs. AlertAnatomySizeIntentRoundedFooter layoutDismissal behaviourControlledCustom action via AlertDialogCloseAccessibilityRTLAPI ReferenceAlertDialog (root)AlertDialogContentAlertDialogHeaderAlertDialogFooterAlertDialogAction, AlertDialogCancelAlertDialogTrigger, AlertDialogCloseSub-componentsNotes