# AlertDialog **Category**: react **URL**: https://www.heroui.com/docs/react/components/alert-dialog **Source**: https://raw.githubusercontent.com/heroui-inc/heroui/refs/heads/v3/apps/docs/content/docs/react/components/(overlays)/alert-dialog.mdx > Modal dialog for critical confirmations requiring user attention and explicit action *** ## Import ```tsx import { AlertDialog } from "@heroui/react"; ``` ### Usage ```tsx "use client"; import {AlertDialog, Button} from "@heroui/react"; export function Default() { return ( Delete project permanently?

This will permanently delete My Awesome Project and all of its data. This action cannot be undone.

); } ``` ### Anatomy Import the AlertDialog component and access all parts using dot notation. ```tsx import {AlertDialog, Button} from "@heroui/react"; export default () => ( {/* Optional: Close button */} {/* Optional: Status icon */} ); ``` ### Statuses ```tsx "use client"; import {AlertDialog, Button} from "@heroui/react"; export function Statuses() { const examples = [ { actions: { cancel: "Stay Signed In", confirm: "Sign Out", }, body: "You'll need to sign in again to access your account. Any unsaved changes will be lost.", classNames: "bg-accent-soft text-accent-soft-foreground", header: "Sign out of your account?", status: "accent", trigger: "Sign Out", }, { actions: { cancel: "Not Yet", confirm: "Mark Complete", }, body: "This will mark the task as complete and notify all team members. The task will be moved to your completed list.", classNames: "bg-success-soft text-success-soft-foreground", header: "Complete this task?", status: "success", trigger: "Complete Task", }, { actions: { cancel: "Keep Editing", confirm: "Discard", }, body: "You have unsaved changes that will be permanently lost. Are you sure you want to discard them?", classNames: "bg-warning-soft text-warning-soft-foreground", header: "Discard unsaved changes?", status: "warning", trigger: "Discard Changes", }, { actions: { cancel: "Cancel", confirm: "Delete Account", }, body: "This will permanently delete your account and remove all your data from our servers. This action is irreversible.", classNames: "bg-danger-soft text-danger-soft-foreground", header: "Delete your account?", status: "danger", trigger: "Delete Account", }, ] as const; return (
{examples.map(({actions, body, classNames, header, status, trigger}) => ( {header}

{body}

))}
); } ``` ### Placements ```tsx "use client"; import {AlertDialog, Button} from "@heroui/react"; export function Placements() { const placements = ["auto", "top", "center", "bottom"] as const; return (
{placements.map((placement) => ( {placement === "auto" ? "Auto Placement" : `${placement.charAt(0).toUpperCase() + placement.slice(1)} Position`}

{placement === "auto" ? "Automatically positions at the bottom on mobile and center on desktop for optimal user experience." : `This dialog is positioned at the ${placement} of the viewport. Critical confirmations are typically centered for maximum attention.`}

))}
); } ``` ### Backdrop Variants ```tsx "use client"; import {AlertDialog, Button} from "@heroui/react"; export function BackdropVariants() { const variants = ["opaque", "blur", "transparent"] as const; return (
{variants.map((variant) => ( Backdrop: {variant.charAt(0).toUpperCase() + variant.slice(1)}

{variant === "opaque" ? "An opaque dark backdrop that completely obscures the background, providing maximum focus on the dialog." : variant === "blur" ? "A blurred backdrop that softly obscures the background while maintaining visual context." : "A transparent backdrop that keeps the background fully visible, useful for less critical confirmations."}

))}
); } ``` ### Sizes ```tsx "use client"; import {Rocket} from "@gravity-ui/icons"; import {AlertDialog, Button} from "@heroui/react"; export function Sizes() { const sizes = ["xs", "sm", "md", "lg", "cover"] as const; return (
{sizes.map((size) => ( Size: {size.charAt(0).toUpperCase() + size.slice(1)}

{size === "cover" ? ( <> This alert dialog uses the cover size variant. It spans the full screen with margins: 16px on mobile and 40px on desktop. Maintains rounded corners and standard padding. Perfect for critical confirmations that need maximum width while preserving alert dialog aesthetics. ) : ( <> This alert dialog uses the {size} size variant. On mobile devices, all sizes adapt to near full-width for optimal viewing. On desktop, each size provides a different maximum width to suit various content needs. )}

))}
); } ``` ### Custom Icon ```tsx "use client"; import {LockOpen} from "@gravity-ui/icons"; import {AlertDialog, Button} from "@heroui/react"; export function CustomIcon() { return ( Reset your password?

We'll send a password reset link to your email address. You'll need to create a new password to regain access to your account.

); } ``` ### Custom Backdrop ```tsx "use client"; import {TriangleExclamation} from "@gravity-ui/icons"; import {AlertDialog, Button} from "@heroui/react"; export function CustomBackdrop() { return ( Permanently delete your account?

This action cannot be undone. All your data, settings, and content will be permanently removed from our servers. The dramatic red backdrop emphasizes the severity and irreversibility of this decision.

); } ``` ### Dismiss Behavior ```tsx "use client"; import {CircleInfo} from "@gravity-ui/icons"; import {AlertDialog, Button} from "@heroui/react"; export function DismissBehavior() { return (

isDismissable

Controls whether the alert dialog can be dismissed by clicking the overlay backdrop. Alert dialogs typically require explicit action, so this defaults to false. Set to{" "} true for less critical confirmations.

isDismissable = false

Clicking the backdrop won't close this alert dialog

Try clicking outside this alert dialog on the overlay - it won't close. You must use the action buttons to dismiss it.

isKeyboardDismissDisabled

Controls whether the ESC key can dismiss the alert dialog. Alert dialogs typically require explicit action, so this defaults to true. When set to false, the ESC key will be enabled.

isKeyboardDismissDisabled = true

ESC key is disabled

Press ESC - nothing happens. You must use the action buttons to dismiss this alert dialog.

); } ``` ### Close Methods ```tsx "use client"; import {AlertDialog, Button} from "@heroui/react"; export function CloseMethods() { return (

Using slot="close"

The simplest way to close a dialog. Add slot="close" to any Button component within the dialog. When clicked, it will automatically close the dialog.

Using slot="close"

Click either button below - both have slot="close" and will close the dialog automatically.

Using Dialog render props

Access the close method from the Dialog's render props. This gives you full control over when and how to close the dialog, allowing you to add custom logic before closing.

{(renderProps) => ( <> Using Dialog render props

The buttons below use the close method from render props. You can add validation or other logic before calling{" "} renderProps.close().

)}
); } ``` ### Controlled State ```tsx "use client"; import {AlertDialog, Button, useOverlayState} from "@heroui/react"; import React from "react"; export function Controlled() { const [isOpen, setIsOpen] = React.useState(false); const state = useOverlayState(); return (

With React.useState()

Control the alert dialog using React's useState{" "} hook for simple state management. Perfect for basic use cases.

Status:{" "} {isOpen ? "open" : "closed"}

Controlled with useState()

This alert dialog is controlled by React's useState hook. Pass{" "} isOpen and onOpenChange props to manage the dialog state externally.

With useOverlayState()

Use the useOverlayState hook for a cleaner API with convenient methods like open(), close(), and{" "} toggle().

Status:{" "} {state.isOpen ? "open" : "closed"}

Controlled with useOverlayState()

The useOverlayState hook provides dedicated methods for common operations. No need to manually create callbacks—just use{" "} state.open(), state.close(), or{" "} state.toggle().

); } ``` ### Custom Trigger ```tsx "use client"; import {TrashBin} from "@gravity-ui/icons"; import {AlertDialog, Button} from "@heroui/react"; export function CustomTrigger() { return (

Delete Item

Permanently remove this item

Delete this item?

Use AlertDialog.Trigger to create custom trigger elements beyond standard buttons. This example shows a card-style trigger with icons and descriptive text.

); } ``` ### Custom Animations ```tsx "use client"; import {ArrowUpFromLine, Sparkles} from "@gravity-ui/icons"; import {AlertDialog, Button} from "@heroui/react"; import React from "react"; const iconMap: Record> = { "gravity-ui:arrow-up-from-line": ArrowUpFromLine, "gravity-ui:sparkles": Sparkles, }; export function CustomAnimations() { const animations = [ { classNames: { backdrop: [ "data-[entering]:duration-400", "data-[entering]:ease-[cubic-bezier(0.16,1,0.3,1)]", "data-[exiting]:duration-200", "data-[exiting]:ease-[cubic-bezier(0.7,0,0.84,0)]", ].join(" "), container: [ "data-[entering]:animate-in", "data-[entering]:fade-in-0", "data-[entering]:zoom-in-95", "data-[entering]:duration-400", "data-[entering]:ease-[cubic-bezier(0.16,1,0.3,1)]", "data-[exiting]:animate-out", "data-[exiting]:fade-out-0", "data-[exiting]:zoom-out-95", "data-[exiting]:duration-200", "data-[exiting]:ease-[cubic-bezier(0.7,0,0.84,0)]", ].join(" "), }, description: "Physics-based elastic scaling. Simulates a high-damping spring system with fast transient response and prolonged settling time. Ideal for Alert Dialogs and Modals.", icon: "gravity-ui:sparkles", name: "Kinematic Scale", }, { classNames: { backdrop: [ "data-[entering]:duration-500", "data-[entering]:ease-[cubic-bezier(0.25,1,0.5,1)]", "data-[exiting]:duration-200", "data-[exiting]:ease-[cubic-bezier(0.5,0,0.75,0)]", ].join(" "), container: [ "data-[entering]:animate-in", "data-[entering]:fade-in-0", "data-[entering]:slide-in-from-bottom-4", "data-[entering]:duration-500", "data-[entering]:ease-[cubic-bezier(0.25,1,0.5,1)]", "data-[exiting]:animate-out", "data-[exiting]:fade-out-0", "data-[exiting]:slide-out-to-bottom-2", "data-[exiting]:duration-200", "data-[exiting]:ease-[cubic-bezier(0.5,0,0.75,0)]", ].join(" "), }, description: "Simulates movement through a medium with fluid resistance. Eliminates mechanical linearity for a natural, grounded feel. Perfect for Bottom Sheets or Toasts.", icon: "gravity-ui:arrow-up-from-line", name: "Fluid Slide", }, ]; return (
{animations.map(({classNames, description, icon, name}) => { const IconComponent = iconMap[icon]; return ( {!!IconComponent && } {name} Animation

{description}

); })}
); } ``` ### Custom Portal ```tsx "use client"; import {AlertDialog, Button} from "@heroui/react"; import {useCallback, useRef, useState} from "react"; export function CustomPortal() { const portalRef = useRef(null); const [portalContainer, setPortalContainer] = useState(null); const setPortalRef = useCallback((node: HTMLDivElement | null) => { portalRef.current = node; setPortalContainer(node); }, []); return (

Render alert dialogs inside a custom container instead of document.body

Apply transform: translateZ(0) to the container to create a new stacking context.

{!!portalContainer && ( Custom Portal

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.

)}
); } ``` ## Related Components - **Button**: Allows a user to perform an action - **CloseButton**: Button for dismissing overlays ## Styling ### Passing Tailwind CSS classes ```tsx import {AlertDialog, Button} from "@heroui/react"; function CustomAlertDialog() { return ( Custom Styled Alert

This alert dialog has custom styling applied via Tailwind classes

); } ``` ### Customizing the component classes To customize the AlertDialog component classes, you can use the `@layer components` directive.
[Learn more](https://tailwindcss.com/docs/adding-custom-styles#adding-component-classes). ```css @layer components { .alert-dialog__backdrop { @apply bg-gradient-to-br from-black/60 to-black/80; } .alert-dialog__dialog { @apply rounded-2xl border border-red-500/20 shadow-2xl; } .alert-dialog__header { @apply gap-4; } .alert-dialog__icon { @apply size-16; } .alert-dialog__close-trigger { @apply rounded-full bg-white/10 hover:bg-white/20; } } ``` HeroUI follows the [BEM](https://getbem.com/) methodology to ensure component variants and states are reusable and easy to customize. ### CSS Classes The AlertDialog component uses these CSS classes ([View source styles](https://github.com/heroui-inc/heroui/blob/v3/packages/styles/components/alert-dialog.css)): #### Base Classes - `.alert-dialog__trigger` - Trigger element that opens the alert dialog - `.alert-dialog__backdrop` - Overlay backdrop behind the dialog - `.alert-dialog__container` - Positioning wrapper with placement support - `.alert-dialog__dialog` - Dialog content container - `.alert-dialog__header` - Header section for icon and title - `.alert-dialog__heading` - Heading text styles - `.alert-dialog__body` - Main content area - `.alert-dialog__footer` - Footer section for actions - `.alert-dialog__icon` - Icon container with status colors - `.alert-dialog__close-trigger` - Close button element #### Backdrop Variants - `.alert-dialog__backdrop--opaque` - Opaque colored backdrop (default) - `.alert-dialog__backdrop--blur` - Blurred backdrop with glass effect - `.alert-dialog__backdrop--transparent` - Transparent backdrop (no overlay) #### Status Variants (Icon) - `.alert-dialog__icon--default` - Default gray status - `.alert-dialog__icon--accent` - Accent blue status - `.alert-dialog__icon--success` - Success green status - `.alert-dialog__icon--warning` - Warning orange status - `.alert-dialog__icon--danger` - Danger red status ### Interactive States The component supports these interactive states: - **Focus**: `:focus-visible` or `[data-focus-visible="true"]` - Applied to trigger, dialog, and close button - **Hover**: `:hover` or `[data-hovered="true"]` - Applied to close button on hover - **Active**: `:active` or `[data-pressed="true"]` - Applied to close button when pressed - **Entering**: `[data-entering]` - Applied during dialog opening animation - **Exiting**: `[data-exiting]` - Applied during dialog closing animation - **Placement**: `[data-placement="*"]` - Applied based on dialog position (auto, top, center, bottom) ## API Reference ### AlertDialog | Prop | Type | Default | Description | | ---------- | ----------- | ------- | ------------------------------ | | `children` | `ReactNode` | - | Trigger and container elements | ### AlertDialog.Trigger | Prop | Type | Default | Description | | ----------- | ----------- | ------- | ---------------------- | | `children` | `ReactNode` | - | Custom trigger content | | `className` | `string` | - | CSS classes | ### AlertDialog.Backdrop | Prop | Type | Default | Description | | --------------------------- | ----------------------------------------- | ---------- | ------------------------- | | `variant` | `"opaque" \| "blur" \| "transparent"` | `"opaque"` | Backdrop overlay style | | `isDismissable` | `boolean` | `false` | Close on backdrop click | | `isKeyboardDismissDisabled` | `boolean` | `true` | Disable ESC key to close | | `isOpen` | `boolean` | - | Controlled open state | | `onOpenChange` | `(isOpen: boolean) => void` | - | Open state change handler | | `className` | `string \| (values) => string` | - | Backdrop CSS classes | | `UNSTABLE_portalContainer` | `HTMLElement` | - | Custom portal container | ### AlertDialog.Container | Prop | Type | Default | Description | | ----------- | ----------------------------------------- | -------- | ------------------------- | | `placement` | `"auto" \| "center" \| "top" \| "bottom"` | `"auto"` | Dialog position on screen | | `size` | `"xs" \| "sm" \| "md" \| "lg" \| "cover"` | `"md"` | Alert Dialog size variant | | `className` | `string \| (values) => string` | - | Container CSS classes | ### AlertDialog.Dialog | Prop | Type | Default | Description | | ------------------ | ------------------------------------- | --------------- | -------------------------- | | `children` | `ReactNode \| ({close}) => ReactNode` | - | Content or render function | | `className` | `string` | - | CSS classes | | `role` | `string` | `"alertdialog"` | ARIA role | | `aria-label` | `string` | - | Accessibility label | | `aria-labelledby` | `string` | - | ID of label element | | `aria-describedby` | `string` | - | ID of description element | ### AlertDialog.Header | Prop | Type | Default | Description | | ----------- | ----------- | ------- | ------------------------------------------- | | `children` | `ReactNode` | - | Header content (typically Icon and Heading) | | `className` | `string` | - | CSS classes | ### AlertDialog.Heading | Prop | Type | Default | Description | | ----------- | ----------- | ------- | ------------ | | `children` | `ReactNode` | - | Heading text | | `className` | `string` | - | CSS classes | ### AlertDialog.Body | Prop | Type | Default | Description | | ----------- | ----------- | ------- | ------------ | | `children` | `ReactNode` | - | Body content | | `className` | `string` | - | CSS classes | ### AlertDialog.Footer | Prop | Type | Default | Description | | ----------- | ----------- | ------- | ----------------------------------------- | | `children` | `ReactNode` | - | Footer content (typically action buttons) | | `className` | `string` | - | CSS classes | ### AlertDialog.Icon | Prop | Type | Default | Description | | ----------- | ------------------------------------------------------------- | ---------- | -------------------- | | `children` | `ReactNode` | - | Custom icon element | | `status` | `"default" \| "accent" \| "success" \| "warning" \| "danger"` | `"danger"` | Status color variant | | `className` | `string` | - | CSS classes | ### AlertDialog.CloseTrigger | Prop | Type | Default | Description | | ----------- | ------------------------------ | ------- | ------------------- | | `children` | `ReactNode` | - | Custom close button | | `className` | `string \| (values) => string` | - | CSS classes | ### useOverlayState Hook ```tsx import {useOverlayState} from "@heroui/react"; const state = useOverlayState({ defaultOpen: false, onOpenChange: (isOpen) => console.log(isOpen), }); state.isOpen; // Current state state.open(); // Open dialog state.close(); // Close dialog state.toggle(); // Toggle state state.setOpen(); // Set state directly ``` ## Accessibility Implements [WAI-ARIA AlertDialog pattern](https://www.w3.org/WAI/ARIA/apg/patterns/alertdialog/): - **Focus trap**: Focus locked within alert dialog - **Keyboard**: `ESC` closes (when enabled), `Tab` cycles elements - **Screen readers**: Proper ARIA attributes with `role="alertdialog"` - **Scroll lock**: Body scroll disabled when open - **Required action**: Defaults to requiring explicit user action (no backdrop/ESC dismiss)