Alert Dialog

Ask for confirmation before a consequential action.

Use a modal prompt when an action deserves one last check. It includes a portal overlay, Escape dismissal, and controlled or uncontrolled open state.

tsx
import {  AlertDialog,  AlertDialogAction,  AlertDialogCancel,  AlertDialogContent,  AlertDialogDescription,  AlertDialogFooter,  AlertDialogHeader,  AlertDialogTitle,  AlertDialogTrigger,} from "@/components/ui/alert-dialog"export function Example() {  return (    <AlertDialog>      <AlertDialogTrigger>Ship update</AlertDialogTrigger>      <AlertDialogContent>        <AlertDialogHeader>          <AlertDialogTitle>Ship this docs update?</AlertDialogTitle>          <AlertDialogDescription>            The changelog entry and component pages go live for everyone on the            current namespace.          </AlertDialogDescription>        </AlertDialogHeader>        <AlertDialogFooter>          <AlertDialogCancel>Not yet</AlertDialogCancel>          <AlertDialogAction>Ship</AlertDialogAction>        </AlertDialogFooter>      </AlertDialogContent>    </AlertDialog>  )}

Installation

npx @arctis-sh/@arctis-sh/ui@latest add alert-dialog

Usage

import {  AlertDialog,  AlertDialogAction,  AlertDialogCancel,  AlertDialogContent,  AlertDialogDescription,  AlertDialogFooter,  AlertDialogHeader,  AlertDialogTitle,  AlertDialogTrigger,} from "@/components/ui/alert-dialog"
<AlertDialog>  <AlertDialogTrigger>Publish draft</AlertDialogTrigger>  <AlertDialogContent>    <AlertDialogHeader>      <AlertDialogTitle>Publish this draft?</AlertDialogTitle>      <AlertDialogDescription>        This page will be visible to everyone in the current namespace.      </AlertDialogDescription>    </AlertDialogHeader>    <AlertDialogFooter>      <AlertDialogCancel>Keep editing</AlertDialogCancel>      <AlertDialogAction>Publish</AlertDialogAction>    </AlertDialogFooter>  </AlertDialogContent></AlertDialog>

Composition

AlertDialog
├── AlertDialogTrigger
└── AlertDialogContent
    ├── AlertDialogHeader
    │   ├── AlertDialogMedia
    │   ├── AlertDialogTitle
    │   └── AlertDialogDescription
    └── AlertDialogFooter
        ├── AlertDialogCancel
        └── AlertDialogAction

AlertDialogMedia is optional. When it contains an icon, the title and description sit beside it.

Basic

The trigger opens the dialog. Cancel closes it, while the action confirms the choice.

tsx
import {  AlertDialog,  AlertDialogAction,  AlertDialogCancel,  AlertDialogContent,  AlertDialogDescription,  AlertDialogFooter,  AlertDialogHeader,  AlertDialogTitle,  AlertDialogTrigger,} from "@/components/ui/alert-dialog"export function Example() {  return (    <AlertDialog>      <AlertDialogTrigger>Ship update</AlertDialogTrigger>      <AlertDialogContent>        <AlertDialogHeader>          <AlertDialogTitle>Ship this docs update?</AlertDialogTitle>          <AlertDialogDescription>            The changelog entry and component pages go live for everyone on the            current namespace.          </AlertDialogDescription>        </AlertDialogHeader>        <AlertDialogFooter>          <AlertDialogCancel>Not yet</AlertDialogCancel>          <AlertDialogAction>Ship</AlertDialogAction>        </AlertDialogFooter>      </AlertDialogContent>    </AlertDialog>  )}

Small

Set size="sm" on AlertDialogContent for a more compact panel.

tsx
import {  AlertDialog,  AlertDialogAction,  AlertDialogCancel,  AlertDialogContent,  AlertDialogDescription,  AlertDialogFooter,  AlertDialogHeader,  AlertDialogTitle,  AlertDialogTrigger,} from "@/components/ui/alert-dialog"export function Example() {  return (    <AlertDialog>      <AlertDialogTrigger>Discard edits</AlertDialogTrigger>      <AlertDialogContent size="sm">        <AlertDialogHeader>          <AlertDialogTitle>Discard local edits?</AlertDialogTitle>          <AlertDialogDescription>            Unsaved markdown changes in this tab will be dropped.          </AlertDialogDescription>        </AlertDialogHeader>        <AlertDialogFooter>          <AlertDialogCancel>Keep</AlertDialogCancel>          <AlertDialogAction>Discard</AlertDialogAction>        </AlertDialogFooter>      </AlertDialogContent>    </AlertDialog>  )}

Outline

Set variant="outline" on AlertDialogContent for a bordered panel.

tsx
import {  AlertDialog,  AlertDialogAction,  AlertDialogCancel,  AlertDialogContent,  AlertDialogDescription,  AlertDialogFooter,  AlertDialogHeader,  AlertDialogTitle,  AlertDialogTrigger,} from "@/components/ui/alert-dialog"export function Example() {  return (    <AlertDialog>      <AlertDialogTrigger>Ship update</AlertDialogTrigger>      <AlertDialogContent variant="outline">        <AlertDialogHeader>          <AlertDialogTitle>Ship this docs update?</AlertDialogTitle>          <AlertDialogDescription>            The changelog entry and component pages go live for everyone on the            current namespace.          </AlertDialogDescription>        </AlertDialogHeader>        <AlertDialogFooter>          <AlertDialogCancel>Not yet</AlertDialogCancel>          <AlertDialogAction>Ship</AlertDialogAction>        </AlertDialogFooter>      </AlertDialogContent>    </AlertDialog>  )}

With icon

Use AlertDialogMedia for a leading icon with the copy beside it.

tsx
import {  AlertDialog,  AlertDialogAction,  AlertDialogCancel,  AlertDialogContent,  AlertDialogDescription,  AlertDialogFooter,  AlertDialogHeader,  AlertDialogMedia,  AlertDialogTitle,  AlertDialogTrigger,} from "@/components/ui/alert-dialog"export function Example() {  return (    <AlertDialog>      <AlertDialogTrigger>Pull component</AlertDialogTrigger>      <AlertDialogContent>        <AlertDialogHeader>          <AlertDialogMedia>            <PackageIcon />          </AlertDialogMedia>          <AlertDialogTitle>Add alert to this repo?</AlertDialogTitle>          <AlertDialogDescription>            Files write into src/components/ui. You own them after install —            no package lock-in.          </AlertDialogDescription>        </AlertDialogHeader>        <AlertDialogFooter>          <AlertDialogCancel>Cancel</AlertDialogCancel>          <AlertDialogAction>Add</AlertDialogAction>        </AlertDialogFooter>      </AlertDialogContent>    </AlertDialog>  )}

Small with icon

Combine size="sm" with AlertDialogMedia.

tsx
import {  AlertDialog,  AlertDialogAction,  AlertDialogCancel,  AlertDialogContent,  AlertDialogDescription,  AlertDialogFooter,  AlertDialogHeader,  AlertDialogMedia,  AlertDialogTitle,  AlertDialogTrigger,} from "@/components/ui/alert-dialog"export function Example() {  return (    <AlertDialog>      <AlertDialogTrigger>Revert theme</AlertDialogTrigger>      <AlertDialogContent size="sm">        <AlertDialogHeader>          <AlertDialogMedia>            <WarningIcon />          </AlertDialogMedia>          <AlertDialogTitle>Revert theme tokens?</AlertDialogTitle>          <AlertDialogDescription>            Custom CSS variables snap back to the starter defaults.          </AlertDialogDescription>        </AlertDialogHeader>        <AlertDialogFooter>          <AlertDialogCancel>Cancel</AlertDialogCancel>          <AlertDialogAction>Revert</AlertDialogAction>        </AlertDialogFooter>      </AlertDialogContent>    </AlertDialog>  )}

With image

AlertDialogMedia can span the full width to place a preview image above the copy.

tsx
import {  AlertDialog,  AlertDialogAction,  AlertDialogCancel,  AlertDialogContent,  AlertDialogDescription,  AlertDialogFooter,  AlertDialogHeader,  AlertDialogMedia,  AlertDialogTitle,  AlertDialogTrigger,} from "@/components/ui/alert-dialog"export function Example() {  return (    <AlertDialog>      <AlertDialogTrigger>Open preview</AlertDialogTrigger>      <AlertDialogContent>        <AlertDialogHeader>          <AlertDialogMedia className="col-span-full mb-3 h-44 w-full overflow-hidden rounded-sm p-0 sm:h-52">            <img              src="/assets/brand/demos/alert-dialog-preview.png"              alt=""            />          </AlertDialogMedia>          <AlertDialogTitle className="!col-start-1">            Open staged preview?          </AlertDialogTitle>          <AlertDialogDescription className="!col-start-1">            Share a temporary build of the docs. The link expires after seven            days.          </AlertDialogDescription>        </AlertDialogHeader>        <AlertDialogFooter>          <AlertDialogCancel>Close</AlertDialogCancel>          <AlertDialogAction>Open</AlertDialogAction>        </AlertDialogFooter>      </AlertDialogContent>    </AlertDialog>  )}

Delete confirm

A destructive confirmation with a clear icon and action.

tsx
import {  AlertDialog,  AlertDialogAction,  AlertDialogCancel,  AlertDialogContent,  AlertDialogDescription,  AlertDialogFooter,  AlertDialogHeader,  AlertDialogMedia,  AlertDialogTitle,  AlertDialogTrigger,} from "@/components/ui/alert-dialog"export function Example() {  return (    <AlertDialog>      <AlertDialogTrigger variant="destructive">        Delete demo      </AlertDialogTrigger>      <AlertDialogContent>        <AlertDialogHeader>          <AlertDialogMedia className="bg-destructive/10 text-destructive">            <TrashIcon />          </AlertDialogMedia>          <AlertDialogTitle>Delete this demo scene?</AlertDialogTitle>          <AlertDialogDescription>            The preview and its code sample leave the docs page. You can add            the scene again later from the registry.          </AlertDialogDescription>        </AlertDialogHeader>        <AlertDialogFooter>          <AlertDialogCancel>Cancel</AlertDialogCancel>          <AlertDialogAction variant="destructive">Delete</AlertDialogAction>        </AlertDialogFooter>      </AlertDialogContent>    </AlertDialog>  )}

Type to confirm

Require the user to enter matching text before enabling a destructive action.

tsx
import { useState } from "react"import {  AlertDialog,  AlertDialogAction,  AlertDialogCancel,  AlertDialogContent,  AlertDialogDescription,  AlertDialogFooter,  AlertDialogHeader,  AlertDialogTitle,  AlertDialogTrigger,} from "@/components/ui/alert-dialog"const CONFIRM_TEXT = "drop-namespace"export function Example() {  const [value, setValue] = useState("")  return (    <AlertDialog      onOpenChange={(open) => {        if (!open) setValue("")      }}    >      <AlertDialogTrigger variant="destructive">        Drop namespace      </AlertDialogTrigger>      <AlertDialogContent>        <AlertDialogHeader>          <AlertDialogTitle>Drop @arctis permanently?</AlertDialogTitle>          <AlertDialogDescription>            Installs that point at this namespace will fail. Type{" "}            <span className="font-medium text-foreground">{CONFIRM_TEXT}</span>{" "}            to continue.          </AlertDialogDescription>        </AlertDialogHeader>        <input          value={value}          onChange={(event) => setValue(event.target.value)}          placeholder={CONFIRM_TEXT}          className="mt-4 w-full rounded-sm border border-input bg-background px-3 py-2 text-sm outline-none"        />        <AlertDialogFooter>          <AlertDialogCancel>Cancel</AlertDialogCancel>          <AlertDialogAction            variant="destructive"            disabled={value !== CONFIRM_TEXT}          >            Drop          </AlertDialogAction>        </AlertDialogFooter>      </AlertDialogContent>    </AlertDialog>  )}

API Reference

AlertDialog

PropTypeDefault
openboolean
defaultOpenbooleanfalse
onOpenChange(open: boolean) => void
<AlertDialog>  <AlertDialogTrigger variant="outline">Open</AlertDialogTrigger>  <AlertDialogContent>    <AlertDialogTitle>Are you sure?</AlertDialogTitle>    <AlertDialogDescription>This cannot be undone.</AlertDialogDescription>    <AlertDialogCancel>Cancel</AlertDialogCancel>    <AlertDialogAction>Continue</AlertDialogAction>  </AlertDialogContent></AlertDialog>

AlertDialogTrigger

Renders a Button and accepts the same props, including variant, size, and loading.

PropTypeDefault
variantButton variant"default"
sizeButton size"sm"
classNamestring
<AlertDialogTrigger variant="outline">Open</AlertDialogTrigger>

AlertDialogContent

PropTypeDefault
size"default" | "sm""default"
variant"default" | "outline""default"
classNamestring
<AlertDialogContent>  <AlertDialogTitle>Are you sure?</AlertDialogTitle>  <AlertDialogDescription>This cannot be undone.</AlertDialogDescription></AlertDialogContent>

AlertDialogMedia

PropTypeDefault
classNamestring
<AlertDialogMedia>  <Icon /></AlertDialogMedia>

AlertDialogTitle

PropTypeDefault
classNamestring
<AlertDialogTitle>Are you sure?</AlertDialogTitle>

AlertDialogDescription

PropTypeDefault
classNamestring
<AlertDialogDescription>  This cannot be undone.</AlertDialogDescription>

AlertDialogCancel

PropTypeDefault
classNamestring
<AlertDialogCancel>Cancel</AlertDialogCancel>

AlertDialogAction

PropTypeDefault
variant"default" | "destructive""default"
classNamestring
disabledbooleanfalse
<AlertDialogAction>Continue</AlertDialogAction>