import * as React from "react";
import {
AlertDialog,
AlertDialogClose,
AlertDialogContent,
AlertDialogDescription,
AlertDialogFooter,
AlertDialogHeader,
AlertDialogTitle,
AlertDialogTrigger,
} from "@/components/ui/alert-dialog";
import { Button } from "@/components/ui/button";
export function AlertDialogDemo() {
const [open, setOpen] = React.useState(false);
return (
<AlertDialog open={open} onOpenChange={setOpen}>
<AlertDialogTrigger render={<Button>Delete Item</Button>} />
<AlertDialogContent>
<AlertDialogHeader>
<AlertDialogTitle>Confirm Deletion</AlertDialogTitle>
<AlertDialogDescription>
Are you sure you want to delete this item? This action cannot be
undone.
</AlertDialogDescription>
</AlertDialogHeader>
<AlertDialogFooter>
<AlertDialogClose>Cancel</AlertDialogClose>
<Button variant="destructive" onClick={() => setOpen(false)}>
Delete
</Button>
</AlertDialogFooter>
</AlertDialogContent>
</AlertDialog>
);
}
Installation
npx shadcn@latest add @eo-n/alert-dialog
Import all parts and piece them together.
import {
AlertDialog,
AlertDialogClose,
AlertDialogContent,
AlertDialogDescription,
AlertDialogFooter,
AlertDialogTitle,
AlertDialogTrigger,
} from "@/components/ui/alert-dialog";
<AlertDialog>
<AlertDialogTrigger>Open</AlertDialogTrigger>
<AlertDialogContent>
<AlertDialogTitle>Confirm Deletion</AlertDialogTitle>
<AlertDialogDescription>
Are you sure you want to delete this item? This action cannot be undone.
</AlertDialogDescription>
<AlertDialogFooter>
<AlertDialogClose>Cancel</AlertDialogClose>
<Button>Delete</Button>
</AlertDialogFooter>
</AlertDialogContent>
</AlertDialog>
Examples
Close Confirmation
import * as React from "react";
import {
AlertDialog,
AlertDialogClose,
AlertDialogContent,
AlertDialogDescription,
AlertDialogFooter,
AlertDialogTitle,
} from "@/components/ui/alert-dialog";
import { Button } from "@/components/ui/button";
import {
Dialog,
DialogClose,
DialogContent,
DialogDescription,
DialogFooter,
DialogHeader,
DialogTitle,
DialogTrigger,
} from "@/components/ui/dialog";
import { Textarea } from "@/components/ui/textarea";
export function AlertDialogConfirmation() {
const [dialogOpen, setDialogOpen] = React.useState(false);
const [confirmationOpen, setConfirmationOpen] = React.useState(false);
const [textareaValue, setTextareaValue] = React.useState("");
function handleOpenChange(open: boolean) {
if (!open && textareaValue) {
setConfirmationOpen(true);
} else {
setTextareaValue("");
setDialogOpen(open);
}
}
function handleSubmit(e: React.FormEvent<HTMLFormElement>) {
e.preventDefault();
setDialogOpen(false);
}
return (
<Dialog open={dialogOpen} onOpenChange={handleOpenChange}>
<DialogTrigger render={<Button variant="outline">Feedback</Button>} />
<DialogContent className="sm:max-w-[425px]">
<DialogHeader>
<DialogTitle>Submit Feedback</DialogTitle>
<DialogDescription>
We’d love to hear your thoughts about the seminar. Your feedback
helps us improve future events.
</DialogDescription>
</DialogHeader>
<form onSubmit={handleSubmit} className="flex flex-col gap-5">
<Textarea
required
placeholder="What did you like or suggest improving?"
value={textareaValue}
onChange={(event) => setTextareaValue(event.target.value)}
className="text-sm sm:text-base"
/>
<DialogFooter>
<DialogClose render={<Button variant="outline">Cancel</Button>} />
<Button type="submit">Submit Feedback</Button>
</DialogFooter>
</form>
</DialogContent>
<AlertDialog open={confirmationOpen} onOpenChange={setConfirmationOpen}>
<AlertDialogContent className="flex w-[360px] flex-col items-center">
<AlertDialogTitle>Discard Feedback?</AlertDialogTitle>
<AlertDialogDescription className="text-center">
You’ve started writing feedback. If you close now, your message will
be lost. Are you sure you want to discard it?
</AlertDialogDescription>
<AlertDialogFooter className="w-full">
<AlertDialogClose className="flex-1">
Continue Editing
</AlertDialogClose>
<Button
variant="destructive"
className="flex-1"
onClick={() => {
setConfirmationOpen(false);
setDialogOpen(false);
setTextareaValue("");
}}
>
Discard Feedback
</Button>
</AlertDialogFooter>
</AlertDialogContent>
</AlertDialog>
</Dialog>
);
}
Open On Menu
In order to open a dialog using a menu, control the dialog state and open it imperatively using the onClick
handler on the menu item.
Return Focus Properly
Make sure to also use the dialog’s finalFocus
prop to return focus back
to the menu trigger.
import * as React from "react";
import {
AlertDialog,
AlertDialogContent,
AlertDialogDescription,
AlertDialogTitle,
AlertDialogTrigger,
} from "@/component/ui/dialog";
import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuPositioner,
DropdownMenuTrigger,
} from "@/component/ui/dropdown-menu";
export default function DropdownMenuRadio() {
const menuTriggerRef = React.useRef<HTMLButtonElement>(null);
const [alertDialogOpen, setAlertDialogOpen] = React.useState(false);
return (
<React.Fragment>
<DropdownMenu>
{/* Set the trigger ref */}
<DropdownMenuTrigger ref={menuTriggerRef}>Open</DropdownMenuTrigger>
<DropdownMenuPositioner>
<DropdownMenuContent>
{/* Open the dialog when the menu item is clicked */}
<DropdownMenuItem onClick={() => setAlertDialogOpen(true)}>
Open dialog
</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenuPositioner>
</DropdownMenu>
{/* Control the dialog state */}
<AlertDialog open={alertDialogOpen} onOpenChange={setAlertDialogOpen}>
{/* Return focus to the menu trigger when the dialog is closed */}
<AlertDialogContent finalFocus={menuTriggerRef}>
<AlertDialogTitle>Are you sure you want to proceed?</AlertDialogTitle>
<AlertDialogDescription>
This action may have permanent effects. Please confirm if you want
to continue.
</AlertDialogDescription>
</AlertDialogContent>
</AlertDialog>
</React.Fragment>
);
}