Files
skills/docs/ui/react/react-ui/src/components/alert-dialog/alert-dialog.md
2026-05-29 08:20:56 +01:00

7.3 KiB

AlertDialog

(no submodules)

- alert-dialog.variants — `alertDialogOverlayVariants…
  • alert-dialog.variants — alertDialogOverlayVariants, alertDialogContentVariants, alertDialogHeaderVariants, alertDialogFooterVariants, `…

  • alert-dialog.variants — `alertDialogOverlayVariants…

  • alert-dialog.variants — alertDialogOverlayVariants, alertDialogContentVariants, alertDialogHeaderVariants, alertDialogFooterVariants, `…

  • alert-dialog.variants — `alertDialogOverlayVariants…

  • alert-dialog.variants — alertDialogOverlayVariants, alertDialogContentVariants, alertDialogHeaderVariants, alertDialogFooterVariants, `…

  • alert-dialog.variants — `alertDialogOverlayVariants…

  • alert-dialog.variants — alertDialogOverlayVariants, alertDialogContentVariants, alertDialogHeaderVariants, alertDialogFooterVariants, `…

  • alert-dialog.variants — alertDialogOverlayVariants, alertDialogContentVariants, alertDialogHeaderVariants, alertDialogFooterVariants, `…

Purpose

<AlertDialog> and its sub-components (<AlertDialogTrigger>, <AlertDialogPortal>, <AlertDialogOverlay>, <AlertDialogContent>, <AlertDialogHeader>, <AlertDialogFooter>, <AlertDialogTitle>, <AlertDialogDescription>, <AlertDialogAction>, <AlertDialogCancel>) are the chassis modal CONFIRMATION dialog primitives built on @radix-ui/react-alert-dialog.

The structural difference between <AlertDialog> and <Dialog> is the click-outside-suppression: an alert dialog CANNOT be dismissed by clicking the overlay backdrop — the user MUST press the <AlertDialogAction> or <AlertDialogCancel> button. Use <AlertDialog> for destructive operations (delete / discard / log out) where an accidental backdrop click could lose work; use <Dialog> for everything else.

Per the WAI-ARIA alertdialog pattern, every alert dialog MUST contain an <AlertDialogTitle> so the accessible name is announced. Use className="sr-only" if the visible UI does not need a heading. Radix renders role="alertdialog" (NOT role="dialog") so screen readers know to announce the prompt as a high-priority interrupt.

Features

  • role="alertdialog" (Radix-managed) so screen readers announce a high-priority prompt.
  • Click-outside dismissal SUPPRESSED — only Action / Cancel resolve the dialog.
  • Escape closes (treated as cancel) — Radix-managed.
  • Focus-trap on open; restore-focus to the trigger on close.
  • Four content sizes (sm, default, lg, xl) scale the panel max-width.
  • <AlertDialogAction> defaults to Button variant="default" styling (primary).
  • <AlertDialogCancel> defaults to Button variant="outline" styling (secondary).
  • Theme-driven cva overrides for every slot via useThemedVariants("AlertDialog<Slot>").
  • All sub-components forward refs.
  • motion-reduce:animate-none collapses animations under prefers-reduced-motion: reduce.

Usage: Basic Example

import {
    AlertDialog,
    AlertDialogAction,
    AlertDialogCancel,
    AlertDialogContent,
    AlertDialogDescription,
    AlertDialogFooter,
    AlertDialogHeader,
    AlertDialogTitle,
    AlertDialogTrigger,
} from "@suaveplan/react-ui";

export function ConfirmDelete() {
    return (
        <AlertDialog>
            <AlertDialogTrigger>Delete account</AlertDialogTrigger>
            <AlertDialogContent>
                <AlertDialogHeader>
                    <AlertDialogTitle>Are you sure?</AlertDialogTitle>
                    <AlertDialogDescription>
                        This action cannot be undone.
                    </AlertDialogDescription>
                </AlertDialogHeader>
                <AlertDialogFooter>
                    <AlertDialogCancel>Cancel</AlertDialogCancel>
                    <AlertDialogAction>Delete</AlertDialogAction>
                </AlertDialogFooter>
            </AlertDialogContent>
        </AlertDialog>
    );
}

Usage: Advanced Example

import {
    AlertDialog,
    AlertDialogAction,
    AlertDialogCancel,
    AlertDialogContent,
    AlertDialogDescription,
    AlertDialogFooter,
    AlertDialogHeader,
    AlertDialogTitle,
} from "@suaveplan/react-ui";
import { useState } from "react";

export function ConfirmDestructive({
    title,
    description,
    onConfirm,
}: {
    readonly title: string;
    readonly description: string;
    readonly onConfirm: () => Promise<void>;
}) {
    const [open, setOpen] = useState(false);
    const [busy, setBusy] = useState(false);

    async function handleConfirm() {
        setBusy(true);
        try {
            await onConfirm();
            setOpen(false);
        } finally {
            setBusy(false);
        }
    }

    return (
        <AlertDialog open={open} onOpenChange={setOpen}>
            <AlertDialogContent size="sm">
                <AlertDialogHeader>
                    <AlertDialogTitle>{title}</AlertDialogTitle>
                    <AlertDialogDescription>{description}</AlertDialogDescription>
                </AlertDialogHeader>
                <AlertDialogFooter>
                    <AlertDialogCancel disabled={busy}>Cancel</AlertDialogCancel>
                    <AlertDialogAction onClick={handleConfirm} disabled={busy}>
                        {busy ? "Working…" : "Confirm"}
                    </AlertDialogAction>
                </AlertDialogFooter>
            </AlertDialogContent>
        </AlertDialog>
    );
}

API Reference

<AlertDialog>

Wraps the Radix AlertDialog Root. Same lifecycle props as <Dialog> (open, defaultOpen, onOpenChange).

<AlertDialogContent>

Prop Type Default Description
size "sm" | "default" | "lg" | "xl" "default" Visual variant scaling the panel max-width.

<AlertDialogTitle>

REQUIRED for accessibility. Render className="sr-only" if no visible heading is needed.

<AlertDialogAction>, <AlertDialogCancel>

Renders as buttons with the default Button variant="default" and variant="outline" styling respectively. Activating either resolves the dialog (closes it).

<AlertDialogTrigger>, <AlertDialogPortal>, <AlertDialogOverlay>, <AlertDialogHeader>, <AlertDialogFooter>, <AlertDialogDescription>

Direct re-exports of the Radix sub-components with the chassis cva applied.

Implementation Notes

  • The chassis NEVER assigns a numeric z-index — Radix portals handle stacking.
  • The Action / Cancel button cva is INLINED into AlertDialog rather than reusing <Button> so an ejected source copy stays self-contained (matches the shadcn upstream alert-dialog recipe).
  • <AlertDialogContent> self-portals via <AlertDialogPortal> so consumers do not need to compose the portal manually.
  • The Cancel button uses mt-2 sm:mt-0 so it stacks beneath the Action on small screens (Action becomes the visually emphasised primary-end position) and aligns horizontally above sm.
  • Radix's a11y warning fires when no <AlertDialogDescription> is provided either — the chassis does not enforce this since some single-line confirmations only need a title; consumers can pass aria-describedby={undefined} on <AlertDialogContent> if they want to suppress the warning explicitly.