import * as React from "react";
import {
AlertDialog,
AlertDialogAction,
AlertDialogCancel,
AlertDialogContent,
AlertDialogDescription,
AlertDialogFooter,
AlertDialogHeader,
AlertDialogTitle,
AlertDialogTrigger,
} from "@/components/ui/alert-dialog";
import { Button } from "@/components/ui/button";
export default function AlertDialogBasic() {
const [open, setOpen] = React.useState(false);
return (
<AlertDialog open={open} onOpenChange={setOpen}>
<AlertDialogTrigger render={<Button variant="secondary" />}>Sign out</AlertDialogTrigger>
<AlertDialogContent>
<AlertDialogHeader>
<AlertDialogTitle>Sign out?</AlertDialogTitle>
<AlertDialogDescription>
You’ll need to sign in again on this device.
</AlertDialogDescription>
</AlertDialogHeader>
<AlertDialogFooter>
<AlertDialogCancel>Cancel</AlertDialogCancel>
<AlertDialogAction onClick={() => setOpen(false)}>Sign out</AlertDialogAction>
</AlertDialogFooter>
</AlertDialogContent>
</AlertDialog>
);
}- Add the registryOnce per project
pnpm dlx shadcn@latest registry add @jarvis=https://ui.jarv.is/r/{name}.json - Add alert-dialog
pnpm dlx shadcn@latest add @jarvis/alert-dialog
Usage
import * as React from "react";
import {
AlertDialog,
AlertDialogAction,
AlertDialogCancel,
AlertDialogContent,
AlertDialogDescription,
AlertDialogFooter,
AlertDialogHeader,
AlertDialogTitle,
AlertDialogTrigger,
} from "@/components/ui/alert-dialog";
import { Button } from "@/components/ui/button";
export function LeaveTeam() {
const [open, setOpen] = React.useState(false);
return (
<AlertDialog open={open} onOpenChange={setOpen}>
<AlertDialogTrigger render={<Button variant="secondary" />}>Leave team</AlertDialogTrigger>
<AlertDialogContent>
<AlertDialogHeader>
<AlertDialogTitle>Leave the team?</AlertDialogTitle>
<AlertDialogDescription>You’ll lose access to its projects.</AlertDialogDescription>
</AlertDialogHeader>
<AlertDialogFooter>
<AlertDialogCancel>Cancel</AlertDialogCancel>
<AlertDialogAction onClick={() => setOpen(false)}>Leave</AlertDialogAction>
</AlertDialogFooter>
</AlertDialogContent>
</AlertDialog>
);
}Unlike a Dialog, an alert dialog doesn't close when you click outside it.
AlertDialogCancel closes it, but AlertDialogAction doesn't, so control the dialog with open
and onOpenChange and close it when the action finishes.
Always include an AlertDialogTitle and AlertDialogDescription.
Composition
Examples
Destructive
Set variant="destructive" on the action for things that can't be undone.
import { Trash2Icon } from "lucide-react";
import * as React from "react";
import {
AlertDialog,
AlertDialogAction,
AlertDialogCancel,
AlertDialogContent,
AlertDialogDescription,
AlertDialogFooter,
AlertDialogHeader,
AlertDialogTitle,
AlertDialogTrigger,
} from "@/components/ui/alert-dialog";
import { Button } from "@/components/ui/button";
import { toast } from "@/components/ui/toast";
export default function AlertDialogDestructive() {
const [open, setOpen] = React.useState(false);
return (
<AlertDialog open={open} onOpenChange={setOpen}>
<AlertDialogTrigger render={<Button variant="destructive" />}>
<Trash2Icon />
Delete project
</AlertDialogTrigger>
<AlertDialogContent>
<AlertDialogHeader>
<AlertDialogTitle>Delete “Website redesign”?</AlertDialogTitle>
<AlertDialogDescription>
This permanently deletes the project and its 28 tasks. Anyone with the link will see a
“not found” page. This can’t be undone.
</AlertDialogDescription>
</AlertDialogHeader>
<AlertDialogFooter>
<AlertDialogCancel>Cancel</AlertDialogCancel>
<AlertDialogAction
variant="destructive"
onClick={() => {
setOpen(false);
toast.add({ title: "Project deleted" });
}}
>
Delete
</AlertDialogAction>
</AlertDialogFooter>
</AlertDialogContent>
</AlertDialog>
);
}Props
| Part | Extends |
|---|---|
| AlertDialog | Base UI's AlertDialog.Root |
| AlertDialogTrigger | Base UI's AlertDialog.Trigger |
| AlertDialogPortal | Base UI's AlertDialog.Portal |
| AlertDialogOverlay | Base UI's AlertDialog.Backdrop |
| AlertDialogContent | Base UI's AlertDialog.Popup |
| AlertDialogHeader | <div> |
| AlertDialogFooter | <div> |
| AlertDialogTitle | Base UI's AlertDialog.Title |
| AlertDialogDescription | Base UI's AlertDialog.Description |
| AlertDialogAction | Button |
| AlertDialogCancel | Base UI's AlertDialog.Close |
The tables leave out className, style and render. Parts built on Base UI take them as its styling and composition guides describe.
AlertDialog
| Prop | Type | Default |
|---|---|---|
onOpenChangeEvent handler called when the alert dialog is opened or closed. | ((open: boolean, eventDetails: AlertDialog.Root.ChangeEventDetails) => void) | — |
actionsRefA ref to imperative actions.
| React.RefObject<DialogRootActions | null> | — |
handleA handle to associate the alert dialog with a trigger. If specified, allows external triggers to control the alert dialog's open state. Can be created with the AlertDialog.createHandle() method. | AlertDialog.Handle<unknown> | — |
openWhether the dialog is currently open. | boolean | — |
defaultOpenWhether the dialog is initially open. To render a controlled dialog, use the | boolean | false |
onOpenChangeCompleteEvent handler called after any animations complete when the dialog is opened or closed. | ((open: boolean) => void) | — |
childrenThe content of the dialog.
This can be a regular React node or a render function that receives the | PayloadChildRenderFunction<unknown> | React.ReactNode | — |
triggerIdID of the trigger that the dialog is associated with.
This is useful in conjunction with the | string | null | — |
defaultTriggerIdID of the trigger that the dialog is associated with.
This is useful in conjunction with the | string | null | — |
AlertDialogTrigger
| Prop | Type | Default |
|---|---|---|
handleA handle to associate the trigger with an alert dialog. Can be created with the AlertDialog.createHandle() method. | AlertDialog.Handle<unknown> | — |
nativeButtonWhether the component renders a native | boolean | true |
payloadA payload to pass to the dialog when it is opened. | unknown | — |
idID of the trigger. In addition to being forwarded to the rendered element,
it is also used to specify the active trigger for the dialog in controlled mode (with the DialogRoot | string | — |
AlertDialogPortal
| Prop | Type | Default |
|---|---|---|
keepMountedWhether to keep the portal mounted in the DOM while the popup is hidden. | boolean | false |
containerA parent element to render the portal element into. | HTMLElement | React.RefObject<HTMLElement | ShadowRoot | null> | ShadowRoot | null | — |
AlertDialogOverlay
| Prop | Type | Default |
|---|---|---|
forceRenderWhether the backdrop is forced to render even when nested. | boolean | false |
AlertDialogContent
| Prop | Type | Default |
|---|---|---|
initialFocusDetermines the element to focus when the dialog is opened. By default, focus moves to the first tabbable element inside the popup, except when the dialog is opened by touch — then the popup itself is focused to avoid opening the virtual keyboard.
| boolean | React.RefObject<HTMLElement | null> | ((openType: InteractionType) => boolean | HTMLElement | null | void) | — |
finalFocusDetermines the element to focus when the dialog is closed.
| boolean | React.RefObject<HTMLElement | null> | ((closeType: InteractionType) => boolean | HTMLElement | null | void) | — |
AlertDialogAction
| Prop | Type | Default |
|---|---|---|
focusableWhenDisabledWhether the button should be focusable when disabled. | boolean | false |
nativeButtonWhether the component renders a native | boolean | true |
variant | "destructive" | "ghost" | "link" | "outline" | "primary" | "secondary" | "primary" |
size | "default" | "icon" | "icon-lg" | "icon-sm" | "icon-xs" | "lg" | "sm" | "xs" | "default" |
AlertDialogCancel
| Prop | Type | Default |
|---|---|---|
nativeButtonWhether the component renders a native | boolean | true |
variant | "destructive" | "ghost" | "link" | "outline" | "primary" | "secondary" | "secondary" |
size | "default" | "icon" | "icon-lg" | "icon-sm" | "icon-xs" | "lg" | "sm" | "xs" | "default" |