Browse the docs
ComponentsNo. 04 of 109
Alert Dialog
Modal that asks the user to confirm or cancel before an action, with action and cancel buttons.
Installation
pnpm dlx shadcn@latest add @corsair-ui/alert-dialogNo setup needed: the CLI finds @corsair-ui in the shadcn registry directory. The files land in your project as source: edit them like your own code. More in Installation.
Examples
Confirm a destructive action
Focus starts on Cancel, and a click outside does not close it.
API
| Prop | Type | Default |
|---|---|---|
AlertDialogAction / AlertDialogCancelStyled as the default and outline buttons; both close it. | button | — |
Built on Radix Alert Dialog; every prop it takes is passed through.
Accessibility
- role="alertdialog": for decisions that need an answer.
- Focus starts on Cancel, the safe choice. A click outside does not close it; Escape does.
Compatibility
- Tailwind CSS
- 3.4 and 4, both checked in CI
- React
- 19
- Rendering
- Client component ("use client")
Source
1 file, installed as source you own
alert-dialog.tsxView on GitHub"use client";
import * as AlertDialogPrimitive from "@radix-ui/react-alert-dialog";
import type { ComponentProps } from "react";
import { buttonVariants } from "@/registry/default/ui/button";
import { cn } from "@/registry/default/lib/utils";
/**
* A modal that asks the user to confirm or cancel before something happens,
* such as deleting data. Unlike a dialog, a click on the overlay does not
* close it: the user has to pick an answer or press Escape, which cancels.
* Focus starts on the cancel button, stays trapped inside and returns to the
* trigger afterwards. Screen readers announce it as an alert dialog named by
* `AlertDialogTitle` and described by `AlertDialogDescription`. With reduced
* motion it appears without fading or zooming.
*
* @example
* <AlertDialog>
* <AlertDialogTrigger asChild>
* <Button variant="destructive">Delete</Button>
* </AlertDialogTrigger>
* <AlertDialogContent>
* <AlertDialogHeader>
* <AlertDialogTitle>Delete this file?</AlertDialogTitle>
* <AlertDialogDescription>This cannot be undone.</AlertDialogDescription>
* </AlertDialogHeader>
* <AlertDialogFooter>
* <AlertDialogCancel>Cancel</AlertDialogCancel>
* <AlertDialogAction onClick={remove}>Delete</AlertDialogAction>
* </AlertDialogFooter>
* </AlertDialogContent>
* </AlertDialog>
*/
function AlertDialog(props: ComponentProps<typeof AlertDialogPrimitive.Root>) {
return <AlertDialogPrimitive.Root data-slot="alert-dialog" {...props} />;
}
function AlertDialogTrigger(props: ComponentProps<typeof AlertDialogPrimitive.Trigger>) {
return <AlertDialogPrimitive.Trigger data-slot="alert-dialog-trigger" {...props} />;
}
function AlertDialogPortal(props: ComponentProps<typeof AlertDialogPrimitive.Portal>) {
return <AlertDialogPrimitive.Portal data-slot="alert-dialog-portal" {...props} />;
}
function AlertDialogOverlay({
className,
...props
}: ComponentProps<typeof AlertDialogPrimitive.Overlay>) {
return (
<AlertDialogPrimitive.Overlay
data-slot="alert-dialog-overlay"
className={cn(
"fixed inset-0 z-50 bg-black/50",
// animate-in/out sit behind motion-safe: so reduced motion really turns them off.
"motion-safe:data-[state=open]:animate-in data-[state=open]:fade-in-0",
"motion-safe:data-[state=closed]:animate-out data-[state=closed]:fade-out-0",
className
)}
{...props}
/>
);
}
/** The window itself, rendered in a portal above an overlay. It needs an `AlertDialogTitle`. */
function AlertDialogContent({
className,
...props
}: ComponentProps<typeof AlertDialogPrimitive.Content>) {
return (
<AlertDialogPortal>
<AlertDialogOverlay />
<AlertDialogPrimitive.Content
data-slot="alert-dialog-content"
className={cn(
"bg-background fixed top-1/2 left-1/2 z-50 grid w-full max-w-[calc(100%-2rem)] -translate-x-1/2 -translate-y-1/2 gap-4 rounded-lg border p-6 shadow-lg outline-none sm:max-w-lg",
"motion-safe:data-[state=open]:animate-in data-[state=open]:fade-in-0 data-[state=open]:zoom-in-95",
"motion-safe:data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95",
className
)}
{...props}
/>
</AlertDialogPortal>
);
}
function AlertDialogHeader({ className, ...props }: ComponentProps<"div">) {
return (
<div
data-slot="alert-dialog-header"
className={cn("flex flex-col gap-2 text-center sm:text-left", className)}
{...props}
/>
);
}
function AlertDialogFooter({ className, ...props }: ComponentProps<"div">) {
return (
<div
data-slot="alert-dialog-footer"
className={cn("flex flex-col-reverse gap-2 sm:flex-row sm:justify-end", className)}
{...props}
/>
);
}
/** Names the alert dialog for screen readers. */
function AlertDialogTitle({
className,
...props
}: ComponentProps<typeof AlertDialogPrimitive.Title>) {
return (
<AlertDialogPrimitive.Title
data-slot="alert-dialog-title"
className={cn("text-lg leading-none font-semibold", className)}
{...props}
/>
);
}
/** Read out after the title: say what will happen if the user confirms. */
function AlertDialogDescription({
className,
...props
}: ComponentProps<typeof AlertDialogPrimitive.Description>) {
return (
<AlertDialogPrimitive.Description
data-slot="alert-dialog-description"
className={cn("text-muted-foreground text-sm", className)}
{...props}
/>
);
}
/** Confirms and closes. Styled as a primary button; pass `className` to restyle it. */
function AlertDialogAction({
className,
...props
}: ComponentProps<typeof AlertDialogPrimitive.Action>) {
return (
<AlertDialogPrimitive.Action
data-slot="alert-dialog-action"
className={cn(buttonVariants(), className)}
{...props}
/>
);
}
/** Cancels and closes. Escape does the same. */
function AlertDialogCancel({
className,
...props
}: ComponentProps<typeof AlertDialogPrimitive.Cancel>) {
return (
<AlertDialogPrimitive.Cancel
data-slot="alert-dialog-cancel"
// "outline" is the button variant name, not the Tailwind utility.
// tailwind-compat-ignore-next-line
className={cn(buttonVariants({ variant: "outline" }), className)}
{...props}
/>
);
}
export {
AlertDialog,
AlertDialogAction,
AlertDialogCancel,
AlertDialogContent,
AlertDialogDescription,
AlertDialogFooter,
AlertDialogHeader,
AlertDialogOverlay,
AlertDialogPortal,
AlertDialogTitle,
AlertDialogTrigger,
};