Skip to content

Alert Dialog

A modal confirmation that interrupts the user before a destructive or irreversible action.

Preview

Installation

pnpm add @syntara/react @syntara/tokens
import { AlertDialog } from '@syntara/react';

Usage

import { AlertDialog, Button, DialogTrigger } from '@syntara/react';

export function DeleteCard({ onDelete }: { onDelete: () => Promise<void> }) {
  return (
    <DialogTrigger>
      <Button tone="danger">Delete card</Button>
      <AlertDialog title="Delete this card?" actionLabel="Delete" tone="danger" onAction={onDelete}>
        Scheduled payments on this card will stop. This can’t be undone.
      </AlertDialog>
    </DialogTrigger>
  );
}

Examples

Destructive action

tone="danger" styles the action and focuses Cancel first.

Async action

Returning a promise from onAction shows a pending state until it settles.

Accessibility

KeysAction
TaborShiftTabMoves between Cancel and the action; focus is trapped.
EnterorSpaceActivates the focused button.
EscapeCancels (closes without acting) and returns focus to the trigger. Disabled while pending.
  • role="alertdialog" named by the title and described by the message.
  • Clicking the backdrop does nothing — the user must choose.
  • Initial focus goes to Cancel for danger tone (least destructive choice) and to the action otherwise.
  • Overlays render in a portal on <body>, outside any ThemeScope. When it opens, the overlay looks up data-syntara-theme, data-syntara-scheme, data-syntara-density, dir and lang — each on the nearest ancestor that has it — starting from its trigger (or from where the component is rendered, when controlled), and copies them onto its own root — so it uses the same tenant tokens and direction as the page region it came from, and nested overlays inherit from their parent overlay.

Guidelines

Do

  • Say what will happen in the title and the consequence in the message.
  • Name the action after the outcome: "Delete card", "Publish".

Don’t

  • Don't use it for information that needs no decision — use Alert or a toast.
  • Don't use "Yes" / "No" labels.

API reference

AlertDialog

titleRequired
ReactNode

The question or statement, e.g. "Delete this card?".

childrenRequired
ReactNode

The consequence. Announced as the dialog's description.

actionLabelRequired
ReactNode

Label of the confirming button. Use a specific verb ("Delete card"), not "OK".

cancelLabel
ReactNode

Label of the dismissing button.

Default 'Cancel'

tone
  • defaultdefault
  • danger

danger uses the solid danger Button (variant="primary" tone="danger") and moves initial focus to Cancel; default focuses the action.

onAction
() => void | Promise<unknown>

Runs on the action. The dialog then closes; a returned promise keeps it open and pending until it resolves (and open if it rejects).

isPending
boolean

Shows the action as pending and disables Cancel and Escape, when you track the request yourself.

Default false

size
  • sm
  • mddefault
  • lg

Maximum width.

isOpen / defaultOpen / onOpenChange
boolean / boolean / (isOpen: boolean) => void

Controlled or uncontrolled open state, when not inside a DialogTrigger (e.g. opened from a menu item).

Tokens

The semantic tokens this component reads, grouped by what they control. Swatches show this site’s theme; change a tenant’s brand and the component follows with no code change.

Colour4
text.defaultsurface.raisedtext.subtleborder.subtle
Type9
font.bodyfont.size.mdline-height.normalfont.headingfont.size.lgfont.weight.semiboldline-height.snugfont.heading-trackingfont.size.sm
Space and size7
space.16space.4card-insetspace.1control-heightfield-gapspace.2
Shape1
radius.container
Depth4
glass.blurshadow.overlayglass.opacityhairline
Motion7
motion.duration.normalmotion.easing-outmotion.duration.fastmotion.easingmotion.duration.springmotion.springmotion.duration.slow
Other2
sheenrim