1
ComponentsFeedback

Alert Dialog

Alert Dialog asks users to confirm a blocking or destructive decision before the application continues.

Purpose

Alert Dialog asks the user to confirm a blocking or destructive decision before the application continues. Use Dialog for ordinary modal forms and Alert for non-blocking inline feedback.

Destructive confirmation

import { AlertDialog, AlertDialogClose, AlertDialogPopup, AlertDialogTrigger } from "@/components/ui/alert-dialog";
import { Button } from "@/components/ui/button";

export function Example() {
  return (
    <AlertDialog>
      <AlertDialogTrigger render={<Button variant="destructive-outline" />}>
        Delete project
      </AlertDialogTrigger>
      <AlertDialogPopup>
        <AlertDialogClose render={<Button variant="destructive" />}>Delete</AlertDialogClose>
      </AlertDialogPopup>
    </AlertDialog>
  );
}

Installation

With the Siteplane registry alias configured, add the component and import the installed source from your app.

CLI

pnpm dlx shadcn@4.16.1 add @siteplane/alert-dialog

Import

import { AlertDialog, AlertDialogClose, AlertDialogCreateHandle, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogPopup, AlertDialogTitle, AlertDialogTrigger } from "@/components/ui/alert-dialog";

Need the machine-readable source metadata? View registry JSON.

Usage

Use Alert Dialog for irreversible decisions. The destructive action belongs inside the dialog, not as loud inline chrome.

import { AlertDialog, AlertDialogClose, AlertDialogPopup, AlertDialogTrigger } from "@/components/ui/alert-dialog";
import { Button } from "@/components/ui/button";

export function Example() {
  return (
    <AlertDialog>
      <AlertDialogTrigger render={<Button variant="destructive-outline" />}>
        Delete project
      </AlertDialogTrigger>
      <AlertDialogPopup>
        <AlertDialogClose render={<Button variant="destructive" />}>Delete</AlertDialogClose>
      </AlertDialogPopup>
    </AlertDialog>
  );
}

Examples

Footer density, status icons and close guards are compositions of the same primitive. Reversible modal forms belong in Dialog. On small screens the popup sticks to the bottom edge by default (bottomStickOnMobile).

With status icon

<AlertDialogPopup>
  <AlertDialogHeader>
    <div className="flex items-start gap-3 text-left">
      <TriangleAlertIcon className="mt-0.5 size-5 shrink-0 text-warning" />
      <div className="grid gap-1">
        <AlertDialogTitle>Replace published workspace?</AlertDialogTitle>
        <AlertDialogDescription>
          Members keep the current workspace until the replacement finishes publishing.
        </AlertDialogDescription>
      </div>
    </div>
  </AlertDialogHeader>
  <AlertDialogFooter>
    <AlertDialogClose render={<Button variant="secondary" />}>Cancel</AlertDialogClose>
    <AlertDialogClose render={<Button />}>Replace</AlertDialogClose>
  </AlertDialogFooter>
</AlertDialogPopup>

Close confirmation

A controlled alert guards closing a dirty dialog. Type into the message and dismiss the dialog to trigger it.

const [dialogOpen, setDialogOpen] = useState(false);
const [confirmOpen, setConfirmOpen] = useState(false);
const [value, setValue] = useState("");

<Dialog
  onOpenChange={(open) => {
    if (!open && value) {
      setConfirmOpen(true);
      return;
    }
    setDialogOpen(open);
  }}
  open={dialogOpen}
>
  <DialogTrigger render={<Button variant="outline" />}>Compose</DialogTrigger>
  <DialogPopup showCloseButton={false}>{/* form with textarea */}</DialogPopup>
  <AlertDialog onOpenChange={setConfirmOpen} open={confirmOpen}>
    <AlertDialogPopup>
      <AlertDialogHeader>
        <AlertDialogTitle>Discard changes?</AlertDialogTitle>
        <AlertDialogDescription>Your message will be lost.</AlertDialogDescription>
      </AlertDialogHeader>
      <AlertDialogFooter>
        <AlertDialogClose render={<Button variant="ghost" />}>Go back</AlertDialogClose>
        <Button
          onClick={() => {
            setConfirmOpen(false);
            setValue("");
            setDialogOpen(false);
          }}
        >
          Discard
        </Button>
      </AlertDialogFooter>
    </AlertDialogPopup>
  </AlertDialog>
</Dialog>

API Reference

The reference lists the source-owned exports and props that are easy to miss in visual examples. Inherited Base UI props remain available unless the wrapper narrows them.

  • Every composition uses AlertDialogTrigger, AlertDialogPopup, AlertDialogTitle, AlertDialogDescription, and explicit cancel and confirm actions.
  • AlertDialogCreateHandle supports one shared confirmation dialog with detached triggers or imperative opening.
  • AlertDialogPopup bottomStickOnMobile={false} keeps the popup centered on small screens instead of attaching it to the bottom edge.
  • AlertDialogFooter variant="bare" removes the separated footer surface.

Motion

Component motion uses the shared Siteplane motion contract. See the global motion guide for provider setup, tokens and reduced-motion behavior.

  • Backdrop, viewport, popup, and mobile positioning use the native Alert Dialog motion and global reduced-motion contract.
  • Do not add local durations, transforms, or motion wrappers.

Accessibility

  • The component renders role="alertdialog" with modal focus management, Escape handling, and focus restoration.
  • Every alert dialog requires a concise AlertDialogTitle and AlertDialogDescription.
  • Cancel and confirm actions must be real buttons. Use AlertDialogClose or controlled state to close the dialog.
  • In dirty-state flows, keep the original dialog open until the user confirms that it may be discarded.

Implementation Guidance

  • Reserve Alert Dialog for decisions that block progress or may cause data loss.
  • Use Dialog for non-destructive modal forms, Alert for persistent inline feedback, and Toast for transient feedback.
  • Preserve the native popup, footer, focus, and dismissal behavior.

On This Page