Components
Alert Dialog
A modal dialog that interrupts the user with important content and expects a response. Use it for irreversible or high-consequence actions.
Import
import {
AppAlertDialog,
AppAlertDialogTrigger,
AppAlertDialogContent,
AppAlertDialogHeader,
AppAlertDialogTitle,
AppAlertDialogDescription,
AppAlertDialogFooter,
AppAlertDialogAction,
AppAlertDialogCancel,
} from "@/components/primitives/AppAlertDialog"Anatomy
The Alert Dialog is composed of several parts that work together. Every usage must include a trigger, content, a title, and at least one action.
<AppAlertDialog>
<AppAlertDialogTrigger asChild>
<AppButton>Open</AppButton>
</AppAlertDialogTrigger>
<AppAlertDialogContent>
<AppAlertDialogHeader>
<AppAlertDialogTitle>Title</AppAlertDialogTitle>
<AppAlertDialogDescription>Description</AppAlertDialogDescription>
</AppAlertDialogHeader>
<AppAlertDialogFooter>
<AppAlertDialogCancel>Cancel</AppAlertDialogCancel>
<AppAlertDialogAction>Confirm</AppAlertDialogAction>
</AppAlertDialogFooter>
</AppAlertDialogContent>
</AppAlertDialog>Variants
Both AppAlertDialogAction and AppAlertDialogCancel accept a variant prop to control their color. Use destructive on the action for irreversible operations.
Destructive action
Secondary action
// Available variants for AppAlertDialogAction and AppAlertDialogCancel
"default" // bg-primary — use for standard confirmations
"destructive" // bg-destructive — use for delete / irreversible actions
"secondary" // bg-secondary — use for lower-emphasis confirmations
"outline" // transparent with border — use for cancel / dismissTrigger
Pass asChild on AppAlertDialogTrigger to use any element as the trigger — typically an AppButton. Without asChild, the trigger renders as a plain <button>.
{/* Recommended — use AppButton as trigger */}
<AppAlertDialogTrigger asChild>
<AppButton variant="destructive">Delete</AppButton>
</AppAlertDialogTrigger>Controlled
Use open and onOpenChange to control the dialog from outside — for example, to open it programmatically without a trigger element.
const [open, setOpen] = useState(false)
<AppAlertDialog open={open} onOpenChange={setOpen}>
<AppAlertDialogContent>
{/* ... */}
</AppAlertDialogContent>
</AppAlertDialog>API Reference
AppAlertDialog and its sub-components extend their underlying Radix UI primitives.
| Prop | Type | Default | Description |
|---|---|---|---|
| open | boolean | — | Controlled open state of the dialog. |
| defaultOpen | boolean | false | Initial open state when uncontrolled. |
| onOpenChange | (open: boolean) => void | — | Callback fired when the open state changes. |
| asChild | boolean | false | On AppAlertDialogTrigger — merges props onto the child element instead of rendering a <button>. |
| variant | "default" | "destructive" | "secondary" | "outline" | "default" | On AppAlertDialogAction and AppAlertDialogCancel — controls the button color using semantic design tokens. |
| — | — | — | AppAlertDialogTitle defaults to text-2xl. AppAlertDialogDescription defaults to text-base. Both overridable via className. |
| className | string | — | Additional Tailwind classes merged via cn(). Applied after variant classes, so it always wins. |
Source
import * as React from "react"
import {
AlertDialog,
AlertDialogPortal,
AlertDialogOverlay,
AlertDialogTrigger,
AlertDialogContent,
AlertDialogHeader,
AlertDialogFooter,
AlertDialogTitle,
AlertDialogDescription,
AlertDialogAction,
AlertDialogCancel,
} from "@/components/ui/alert-dialog"
import { cn } from "@/lib/utils"
const actionVariantClasses = {
default: "bg-primary text-primary-foreground hover:bg-primary/90",
destructive: "bg-destructive text-destructive-foreground hover:bg-destructive/90",
secondary: "bg-secondary text-secondary-foreground hover:bg-secondary/80",
outline: "border border-input bg-transparent hover:bg-accent hover:text-accent-foreground",
} as const
const cancelVariantClasses = {
default: "bg-primary text-primary-foreground hover:bg-primary/90",
destructive: "bg-destructive text-destructive-foreground hover:bg-destructive/90",
secondary: "bg-secondary text-secondary-foreground hover:bg-secondary/80",
outline: "border border-input bg-transparent hover:bg-accent hover:text-accent-foreground",
} as const
type ActionVariant = keyof typeof actionVariantClasses
type AppAlertDialogActionProps = React.ComponentPropsWithoutRef<typeof AlertDialogAction> & {
variant?: ActionVariant
}
const AppAlertDialog = AlertDialog
const AppAlertDialogPortal = AlertDialogPortal
const AppAlertDialogOverlay = AlertDialogOverlay
const AppAlertDialogTrigger = AlertDialogTrigger
const AppAlertDialogContent = AlertDialogContent
const AppAlertDialogHeader = AlertDialogHeader
const AppAlertDialogFooter = AlertDialogFooter
const AppAlertDialogTitle = React.forwardRef<
React.ComponentRef<typeof AlertDialogTitle>,
React.ComponentPropsWithoutRef<typeof AlertDialogTitle>
>(({ className, ...props }, ref) => (
<AlertDialogTitle ref={ref} className={cn("text-2xl", className)} {...props} />
))
AppAlertDialogTitle.displayName = "AppAlertDialogTitle"
const AppAlertDialogDescription = React.forwardRef<
React.ComponentRef<typeof AlertDialogDescription>,
React.ComponentPropsWithoutRef<typeof AlertDialogDescription>
>(({ className, ...props }, ref) => (
<AlertDialogDescription ref={ref} className={cn("text-base", className)} {...props} />
))
AppAlertDialogDescription.displayName = "AppAlertDialogDescription"
const AppAlertDialogAction = React.forwardRef<
React.ComponentRef<typeof AlertDialogAction>,
AppAlertDialogActionProps
>(({ className, variant = "default", ...props }, ref) => (
<AlertDialogAction
ref={ref}
className={cn(actionVariantClasses[variant], className)}
{...props}
/>
))
AppAlertDialogAction.displayName = "AppAlertDialogAction"
const AppAlertDialogCancel = React.forwardRef<
React.ComponentRef<typeof AlertDialogCancel>,
AppAlertDialogActionProps
>(({ className, variant = "default", ...props }, ref) => (
<AlertDialogCancel
ref={ref}
className={cn(cancelVariantClasses[variant], className)}
{...props}
/>
))
AppAlertDialogCancel.displayName = "AppAlertDialogCancel"
export {
AppAlertDialog,
AppAlertDialogPortal,
AppAlertDialogOverlay,
AppAlertDialogTrigger,
AppAlertDialogContent,
AppAlertDialogHeader,
AppAlertDialogFooter,
AppAlertDialogTitle,
AppAlertDialogDescription,
AppAlertDialogAction,
AppAlertDialogCancel,
}
export type { AppAlertDialogActionProps, ActionVariant }