Skip to content
Components

AlertDialog

A modal that asks the user to confirm a destructive action. Same look as Dialog but narrower, with no corner close. Focus starts on Cancel, and a scrim click does not close it.

Preview

Props

  • open
  • defaultOpen
import { AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogTitle, AlertDialogTrigger } from "@/components/ui/alert-dialog"
import { Button } from "@/components/ui/button"

<AlertDialog>
  <AlertDialogTrigger asChild>
    <Button variant="destructive-soft">Delete project</Button>
  </AlertDialogTrigger>
  <AlertDialogContent>
    <AlertDialogHeader>
      <AlertDialogTitle>Delete project?</AlertDialogTitle>
      <AlertDialogDescription>This removes the project and all its files for everyone on your team. You can't undo it.</AlertDialogDescription>
    </AlertDialogHeader>
    <AlertDialogFooter>
      <AlertDialogCancel>Cancel</AlertDialogCancel>
      <AlertDialogAction>Delete project</AlertDialogAction>
    </AlertDialogFooter>
  </AlertDialogContent>
</AlertDialog>

Usage

When to use

  • Confirm an action that destroys data or can't be undone, such as deleting a project.
  • Guard a destructive action against a stray key press or click: focus starts on Cancel, and a scrim click doesn't close the dialog.

When not to use

  • Forms, non-destructive choices, or confirming an action that destroys no data and can be undone. Use Dialog.
  • A status that asks for no decision, such as a failed build. Use Badge.

Examples

Delete project

import { AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogTitle, AlertDialogTrigger } from "@/components/ui/alert-dialog"
import { Button } from "@/components/ui/button"

<AlertDialog>
  <AlertDialogTrigger asChild>
    <Button variant="destructive-soft">Delete project</Button>
  </AlertDialogTrigger>
  <AlertDialogContent>
    <AlertDialogHeader>
      <AlertDialogTitle>Delete project?</AlertDialogTitle>
      <AlertDialogDescription>This removes the project and all its files for everyone on your team. You can't undo it.</AlertDialogDescription>
    </AlertDialogHeader>
    <AlertDialogFooter>
      <AlertDialogCancel>Cancel</AlertDialogCancel>
      <AlertDialogAction>Delete project</AlertDialogAction>
    </AlertDialogFooter>
  </AlertDialogContent>
</AlertDialog>

Do and don't

Do

  • Use it only to confirm an action that destroys data or can't be undone.
  • Write the title as the question and the action button as the verb plus the object ("Delete project").
  • Say in the description what is lost and for whom.
  • Keep Cancel first in the footer markup; the footer puts it left on desktop and at the bottom on mobile.

Don't

  • Don't label the action "Continue", "OK" or "Yes".
  • Don't add a corner close or close on a scrim click.
  • Don't move initial focus to the action button.
  • Don't use it for forms or non-destructive choices; use Dialog.
  • Don't leave out AlertDialogDescription.

Props

NameTypeValuesDefaultDescription
openboolean--Set on AlertDialog. Whether the dialog is open, when you control it. Pair it with onOpenChange. Only on web.
defaultOpenboolean-falseSet on AlertDialog. Opens the dialog on first render, when you don't control it. Only on web.
onOpenChangefunction--Set on AlertDialog. Called with true or false when the dialog opens or closes (trigger, Cancel, Action, Escape). Close it yourself after an async action by controlling open. Only on web.

Slots

NameRequiredDescription
triggernoElement that opens the dialog.
titleyesThe question, required for a11y.
descriptionyesWhat happens if the user confirms. Required.
cancelyesAlertDialogCancel: closes only. Secondary button by default.
actionyesAlertDialogAction: closes and runs the destructive action. Destructive button by default, labeled with the action.

Anatomy

PartDescription
rootRoot. Controls open state.
overlayScrim behind the content. color-overlay-scrim. Clicking it does nothing.
contentThe floating panel: Dialog's panel, at most max-w-md wide.
headerTitle and description, left-aligned. No icon in v1.
titleAccessible name. States the question ("Delete project?").
descriptionRequired. Says what will happen and that it can't be undone.
footerCancel (secondary) then the action (destructive). Cancel sits left on desktop and at the bottom on mobile.

Accessibility

Role: alertdialog

KeysAction
EscapeCancels: closes the dialog and returns focus to the trigger.
TabCycles focus inside the dialog (focus trap).
Enter / SpaceActivates the focused button. Cancel has focus when the dialog opens.
  • role="alertdialog", named by AlertDialogTitle (aria-labelledby) and described by AlertDialogDescription (aria-describedby). Both are required.
  • Traps focus and hides the rest of the page from assistive tech (aria-hidden on siblings), same as Dialog.
  • Focus moves to AlertDialogCancel on open, so a stray Enter doesn't destroy anything.
  • No corner close and no close on a scrim click. Cancel and Escape are the only ways out besides the action.
  • Focus returns to the trigger on close.

Install

npx shadcn add https://werewolf-ui.vercel.app/r/alert-dialog.json

This also adds styles/werewolf.css, the tokens every component uses, and any other component it needs. Import that file once in your root CSS, after @import "tailwindcss", with a path relative to that CSS file (from app/globals.css it is @import "../styles/werewolf.css").