Alert Dialog
Blocking confirmation modal requiring an explicit decision. Backs the browser back button.
Examples
Basic
A basic alert dialog with a header, description, and confirm/cancel actions.
import {
AlertDialog,
AlertDialogAction,
AlertDialogCancel,
AlertDialogContent,
AlertDialogDescription,
AlertDialogFooter,
AlertDialogHeader,
AlertDialogTitle,
AlertDialogTrigger,
} from "@codefast/ui/alert-dialog";
import { Button } from "@codefast/ui/button";
export function AlertDialogBasic() {
return (
<AlertDialog>
<AlertDialogTrigger asChild>
<Button variant="outline">Show Dialog</Button>
</AlertDialogTrigger>
<AlertDialogContent>
<AlertDialogHeader>
<AlertDialogTitle>Are you absolutely sure?</AlertDialogTitle>
<AlertDialogDescription>
This action cannot be undone. This will permanently delete your account and remove your data from our
servers.
</AlertDialogDescription>
</AlertDialogHeader>
<AlertDialogFooter>
<AlertDialogCancel>Cancel</AlertDialogCancel>
<AlertDialogAction>Continue</AlertDialogAction>
</AlertDialogFooter>
</AlertDialogContent>
</AlertDialog>
);
}
Small
Use size=sm for a compact, centered confirmation.
import {
AlertDialog,
AlertDialogAction,
AlertDialogCancel,
AlertDialogContent,
AlertDialogDescription,
AlertDialogFooter,
AlertDialogHeader,
AlertDialogTitle,
AlertDialogTrigger,
} from "@codefast/ui/alert-dialog";
import { Button } from "@codefast/ui/button";
export function AlertDialogSmall() {
return (
<AlertDialog>
<AlertDialogTrigger asChild>
<Button variant="outline">Show Dialog</Button>
</AlertDialogTrigger>
<AlertDialogContent size="sm">
<AlertDialogHeader>
<AlertDialogTitle>Allow accessory to connect?</AlertDialogTitle>
<AlertDialogDescription>
Do you want to allow the USB accessory to connect to this device?
</AlertDialogDescription>
</AlertDialogHeader>
<AlertDialogFooter>
<AlertDialogCancel>Don't allow</AlertDialogCancel>
<AlertDialogAction>Allow</AlertDialogAction>
</AlertDialogFooter>
</AlertDialogContent>
</AlertDialog>
);
}
Media
Lead the header with an AlertDialogMedia icon for visual emphasis.
import {
AlertDialog,
AlertDialogAction,
AlertDialogCancel,
AlertDialogContent,
AlertDialogDescription,
AlertDialogFooter,
AlertDialogHeader,
AlertDialogMedia,
AlertDialogTitle,
AlertDialogTrigger,
} from "@codefast/ui/alert-dialog";
import { Button } from "@codefast/ui/button";
import { CircleFadingPlusIcon } from "lucide-react";
export function AlertDialogWithMedia() {
return (
<AlertDialog>
<AlertDialogTrigger asChild>
<Button variant="outline">Share Project</Button>
</AlertDialogTrigger>
<AlertDialogContent>
<AlertDialogHeader>
<AlertDialogMedia>
<CircleFadingPlusIcon />
</AlertDialogMedia>
<AlertDialogTitle>Share this project?</AlertDialogTitle>
<AlertDialogDescription>
Anyone with the link will be able to view and edit this project.
</AlertDialogDescription>
</AlertDialogHeader>
<AlertDialogFooter>
<AlertDialogCancel>Cancel</AlertDialogCancel>
<AlertDialogAction>Share</AlertDialogAction>
</AlertDialogFooter>
</AlertDialogContent>
</AlertDialog>
);
}
Small with media
Combine the compact size with a media icon.
import {
AlertDialog,
AlertDialogAction,
AlertDialogCancel,
AlertDialogContent,
AlertDialogDescription,
AlertDialogFooter,
AlertDialogHeader,
AlertDialogMedia,
AlertDialogTitle,
AlertDialogTrigger,
} from "@codefast/ui/alert-dialog";
import { Button } from "@codefast/ui/button";
import { BluetoothIcon } from "lucide-react";
export function AlertDialogSmallWithMedia() {
return (
<AlertDialog>
<AlertDialogTrigger asChild>
<Button variant="outline">Show Dialog</Button>
</AlertDialogTrigger>
<AlertDialogContent size="sm">
<AlertDialogHeader>
<AlertDialogMedia>
<BluetoothIcon />
</AlertDialogMedia>
<AlertDialogTitle>Allow accessory to connect?</AlertDialogTitle>
<AlertDialogDescription>
Do you want to allow the USB accessory to connect to this device?
</AlertDialogDescription>
</AlertDialogHeader>
<AlertDialogFooter>
<AlertDialogCancel>Don't allow</AlertDialogCancel>
<AlertDialogAction>Allow</AlertDialogAction>
</AlertDialogFooter>
</AlertDialogContent>
</AlertDialog>
);
}
Destructive
Pair a destructive media icon with a destructive action button.
import {
AlertDialog,
AlertDialogAction,
AlertDialogCancel,
AlertDialogContent,
AlertDialogDescription,
AlertDialogFooter,
AlertDialogHeader,
AlertDialogMedia,
AlertDialogTitle,
AlertDialogTrigger,
} from "@codefast/ui/alert-dialog";
import { Button } from "@codefast/ui/button";
import { Trash2Icon } from "lucide-react";
export function AlertDialogDestructive() {
return (
<AlertDialog>
<AlertDialogTrigger asChild>
<Button variant="destructive">Delete Chat</Button>
</AlertDialogTrigger>
<AlertDialogContent size="sm">
<AlertDialogHeader>
<AlertDialogMedia className="bg-destructive/10 text-destructive dark:bg-destructive/20 dark:text-destructive">
<Trash2Icon />
</AlertDialogMedia>
<AlertDialogTitle>Delete chat?</AlertDialogTitle>
<AlertDialogDescription>
This will permanently delete this chat conversation. View <a href="/">Settings</a> delete any memories saved
during this chat.
</AlertDialogDescription>
</AlertDialogHeader>
<AlertDialogFooter>
<AlertDialogCancel variant="outline">Cancel</AlertDialogCancel>
<AlertDialogAction variant="destructive">Delete</AlertDialogAction>
</AlertDialogFooter>
</AlertDialogContent>
</AlertDialog>
);
}
RTL
Right-to-left layout support for languages such as Arabic and Hebrew.
Translations are AI-generated for demonstration and may be imperfect.
import {
AlertDialog,
AlertDialogAction,
AlertDialogCancel,
AlertDialogContent,
AlertDialogDescription,
AlertDialogFooter,
AlertDialogHeader,
AlertDialogMedia,
AlertDialogTitle,
AlertDialogTrigger,
} from "@codefast/ui/alert-dialog";
import { Button } from "@codefast/ui/button";
import { BluetoothIcon } from "lucide-react";
import type { Translations } from "#/features/components-catalog/components/detail/language";
import { useTranslation } from "#/features/components-catalog/components/detail/language-context";
const translations: Translations = {
en: {
dir: "ltr",
values: {
showDialog: "Show Dialog",
showDialogSm: "Show Dialog (sm)",
title: "Are you absolutely sure?",
description: "This action cannot be undone. This will permanently delete your account from our servers.",
cancel: "Cancel",
continue: "Continue",
smallTitle: "Allow accessory to connect?",
smallDescription: "Do you want to allow the USB accessory to connect to this device?",
dontAllow: "Don't allow",
allow: "Allow",
},
},
ar: {
dir: "rtl",
values: {
showDialog: "إظهار الحوار",
showDialogSm: "إظهار الحوار (صغير)",
title: "هل أنت متأكد تمامًا؟",
description: "لا يمكن التراجع عن هذا الإجراء. سيؤدي هذا إلى حذف حسابك نهائيًا من خوادمنا.",
cancel: "إلغاء",
continue: "متابعة",
smallTitle: "السماح للملحق بالاتصال؟",
smallDescription: "هل تريد السماح لملحق USB بالاتصال بهذا الجهاز؟",
dontAllow: "عدم السماح",
allow: "السماح",
},
},
he: {
dir: "rtl",
values: {
showDialog: "הצג דיאלוג",
showDialogSm: "הצג דיאלוג (קטן)",
title: "האם אתה בטוח לחלוטין?",
description: "פעולה זו לא ניתנת לביטול. זה ימחק לצמיתות את החשבון שלך מהשרתים שלנו.",
cancel: "ביטול",
continue: "המשך",
smallTitle: "לאפשר להתקן להתחבר?",
smallDescription: "האם אתה רוצה לאפשר להתקן USB להתחבר למכשיר זה?",
dontAllow: "אל תאפשר",
allow: "אפשר",
},
},
};
export function AlertDialogRtl() {
const { dir, t, language } = useTranslation(translations, "ar");
return (
<div className="flex gap-4" dir={dir}>
<AlertDialog>
<AlertDialogTrigger asChild>
<Button variant="outline">{t.showDialog}</Button>
</AlertDialogTrigger>
<AlertDialogContent dir={dir} data-lang={dir === "rtl" ? language : undefined}>
<AlertDialogHeader>
<AlertDialogTitle>{t.title}</AlertDialogTitle>
<AlertDialogDescription>{t.description}</AlertDialogDescription>
</AlertDialogHeader>
<AlertDialogFooter>
<AlertDialogCancel>{t.cancel}</AlertDialogCancel>
<AlertDialogAction>{t.continue}</AlertDialogAction>
</AlertDialogFooter>
</AlertDialogContent>
</AlertDialog>
<AlertDialog>
<AlertDialogTrigger asChild>
<Button variant="outline">{t.showDialogSm}</Button>
</AlertDialogTrigger>
<AlertDialogContent size="sm" dir={dir} data-lang={dir === "rtl" ? language : undefined}>
<AlertDialogHeader>
<AlertDialogMedia>
<BluetoothIcon />
</AlertDialogMedia>
<AlertDialogTitle>{t.smallTitle}</AlertDialogTitle>
<AlertDialogDescription>{t.smallDescription}</AlertDialogDescription>
</AlertDialogHeader>
<AlertDialogFooter>
<AlertDialogCancel>{t.dontAllow}</AlertDialogCancel>
<AlertDialogAction>{t.allow}</AlertDialogAction>
</AlertDialogFooter>
</AlertDialogContent>
</AlertDialog>
</div>
);
}
Anatomy
How the parts nest — every slot the component exposes, in composition order.
Features
- AlertDialogAction/AlertDialogCancel already render a styled Button internally (default/outline variants) — no need to nest your own Button.
- AlertDialogMedia adds a leading icon slot in the header for visual emphasis.
- size="sm" centers a compact dialog and switches the footer to a 2-column button grid instead of stacked/inline buttons.
- AlertDialogBody is a codefast addition over upstream Radix — long content scrolls on its own while Header/Footer stay pinned, same as DialogBody.
API reference
Props for each part of the component. All native element props are also forwarded.
AlertDialog
Root. A modal that traps focus and requires an explicit choice.
openbooleanThe controlled open state.
defaultOpenbooleanThe open state when initially rendered (uncontrolled).
Default
falseonOpenChange(open: boolean) => voidCalled when the open state changes.
AlertDialogAction
Confirms the action. Renders as a styled Button (variant defaults to default).
onClick(event) => voidConfirms and closes the dialog.
AlertDialogCancel
Dismisses without confirming. Renders as a styled Button (variant defaults to outline).
onClick(event) => voidCancels and closes the dialog.
Accessibility
Built to be keyboard-navigable and screen-reader friendly out of the box.
| Key | Function |
|---|---|
| Tab | Cycles focus within the dialog (trapped). |
| Esc | Triggers Cancel and closes the dialog. |
- Focus moves to the dialog on open; Cancel is the default focus target.
- Title and description are wired to aria-labelledby / aria-describedby.
- Unlike Dialog, it must not be dismissed by clicking the backdrop.
Guidelines
Conventions that keep usage consistent across an app.
Do
- Use for irreversible or risky actions (delete, sign out everywhere).
- Label the action with the verb, e.g. “Delete”, not “OK”.
Don’t
- Don’t use for routine, reversible tasks — that’s a Dialog.
- Don’t make Cancel and the destructive action look identical.
Explore further
Ready to integrate?
Follow the Getting Started guide to install @codefast/ui, or browse the full component gallery.