eo-n/ui
UIComponentsAlert Dialog

Alert Dialog

Prompts the user for a response before continuing.

Installation

CLI

npx shadcn@latest add "https://eo-n.vercel.app/r/alert-dialog"

Manual

Copy and paste the following code into your project.

"use client";
 
import * as React from "react";
import { AlertDialog as AlertDialogPrimitive } from "@base-ui-components/react/alert-dialog";
 
import { cn } from "@/lib/utils";
import { buttonVariants } from "@/components/ui/button";
 
function AlertDialog({
  ...props
}: React.ComponentProps<typeof AlertDialogPrimitive.Root>) {
  return <AlertDialogPrimitive.Root data-slot="alert-dialog" {...props} />;
}
 
function AlertDialogTrigger({
  ...props
}: React.ComponentProps<typeof AlertDialogPrimitive.Trigger>) {
  return (
    <AlertDialogPrimitive.Trigger data-slot="alert-dialog-trigger" {...props} />
  );
}
 
function AlertDialogPortal({
  ...props
}: React.ComponentProps<typeof AlertDialogPrimitive.Portal>) {
  return (
    <AlertDialogPrimitive.Portal data-slot="alert-dialog-portal" {...props} />
  );
}
 
function AlertDialogBackdrop({
  className,
  ...props
}: React.ComponentProps<typeof AlertDialogPrimitive.Backdrop>) {
  return (
    <AlertDialogPrimitive.Backdrop
      data-slot="alert-dialog-backdrop"
      className={cn(
        "fixed inset-0 z-50 bg-black/50 backdrop-blur-[1.5px] transition-colors duration-150 ease-out data-[ending-style]:opacity-0 data-[starting-style]:opacity-0",
        className
      )}
      {...props}
    />
  );
}
 
function AlertDialogContent({
  className,
  children,
  ...props
}: React.ComponentProps<typeof AlertDialogPrimitive.Popup>) {
  return (
    <AlertDialogPortal>
      <AlertDialogBackdrop />
      <AlertDialogPrimitive.Popup
        data-slot="alert-dialog-content"
        className={cn(
          "bg-background fixed top-[50%] left-[50%] z-50 grid w-full max-w-[calc(100%-2rem)] translate-x-[-50%] translate-y-[-50%] gap-4 rounded-lg border p-6 shadow-lg transition-all duration-150 ease-out outline-none sm:max-w-lg",
          "top-[calc(50%+1rem*var(--nested-dialogs))] scale-[calc(1-0.05*var(--nested-dialogs))] data-[ending-style]:top-[50.25%] data-[ending-style]:scale-95 data-[ending-style]:opacity-0 data-[starting-style]:top-[50.25%] data-[starting-style]:scale-95 data-[starting-style]:opacity-0",
          "data-[nested-dialog-open]:after:absolute data-[nested-dialog-open]:after:inset-0 data-[nested-dialog-open]:after:rounded-[inherit] data-[nested-dialog-open]:after:bg-black/5 data-[nested-dialog-open]:after:backdrop-blur-[1.5px]",
          className
        )}
        {...props}
      >
        {children}
      </AlertDialogPrimitive.Popup>
    </AlertDialogPortal>
  );
}
 
function AlertDialogHeader({
  className,
  ...props
}: React.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
}: React.ComponentProps<"div">) {
  return (
    <div
      data-slot="dialog-footer"
      className={cn(
        "flex flex-col-reverse gap-2 sm:flex-row sm:justify-end",
        className
      )}
      {...props}
    />
  );
}
 
function AlertDialogTitle({
  className,
  ...props
}: React.ComponentProps<typeof AlertDialogPrimitive.Title>) {
  return (
    <AlertDialogPrimitive.Title
      data-slot="dialog-title"
      className={cn("text-lg font-semibold", className)}
      {...props}
    />
  );
}
 
function AlertDialogDescription({
  className,
  ...props
}: React.ComponentProps<typeof AlertDialogPrimitive.Description>) {
  return (
    <AlertDialogPrimitive.Description
      data-slot="dialog-description"
      className={cn("text-muted-foreground text-sm", className)}
      {...props}
    />
  );
}
 
function AlertDialogClose({
  className,
  ...props
}: React.ComponentProps<typeof AlertDialogPrimitive.Close>) {
  return (
    <AlertDialogPrimitive.Close
      data-slot="alert-dialog-close"
      className={cn(buttonVariants({ variant: "outline" }), className)}
      {...props}
    />
  );
}
 
export {
  AlertDialog,
  AlertDialogTrigger,
  AlertDialogPortal,
  AlertDialogBackdrop,
  AlertDialogContent,
  AlertDialogHeader,
  AlertDialogFooter,
  AlertDialogTitle,
  AlertDialogDescription,
  AlertDialogClose,
};
Update the import paths to match your project setup.

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

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>
  );
}

On this page