AlertDialog
Alert dialogs require an explicit response before a consequential action proceeds.
Overview and decision boundary
Use AlertDialog when a destructive or difficult-to-reverse action must pause for one explicit response.
Do not hide side effects, default focus to a destructive action, or put multi-step workflows in AlertDialog.
import * as React from 'react';import { AlertDialog, AlertDialogAction, AlertDialogBackdrop, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogPortal, AlertDialogTitle, AlertDialogTrigger, Button } from '@nerio-ui/ui/client';function DeleteProjectDialog() { const cancelRef = React.useRef<HTMLButtonElement>(null); return ( <AlertDialog> <AlertDialogTrigger render={<Button variant="danger">Delete project</Button>} /> <AlertDialogPortal> <AlertDialogBackdrop /> <AlertDialogContent initialFocus={cancelRef}> <AlertDialogHeader> <AlertDialogTitle>Delete project?</AlertDialogTitle> <AlertDialogDescription>This permanently removes the project and cannot be undone.</AlertDialogDescription> </AlertDialogHeader> <AlertDialogFooter> <AlertDialogCancel ref={cancelRef} render={<Button variant="secondary">Cancel</Button>} /> <AlertDialogAction render={<Button variant="danger" onClick={deleteProject}>Delete project</Button>} /> </AlertDialogFooter> </AlertDialogContent> </AlertDialogPortal> </AlertDialog> );}Advanced destructive confirmation
Exact-name confirmation is optional consumer-owned product policy. Compose it inside AlertDialogBody when a high-risk action needs a stronger response than the primitive confirmation boundary.
import * as React from 'react';import { AlertDialog, AlertDialogAction, AlertDialogBackdrop, AlertDialogBody, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogPortal, AlertDialogTitle, AlertDialogTrigger, Button, Field, Input } from '@nerio-ui/ui/client';function DeleteProjectDialog() { const cancelRef = React.useRef<HTMLButtonElement>(null); const projectName = "Nerio"; const [confirmation, setConfirmation] = React.useState(""); const isConfirmed = confirmation === projectName; return ( <AlertDialog onOpenChange={(open) => !open && setConfirmation("")}> <AlertDialogTrigger render={<Button variant="danger">Delete project</Button>} /> <AlertDialogPortal> <AlertDialogBackdrop /> <AlertDialogContent initialFocus={cancelRef}> <AlertDialogHeader> <AlertDialogTitle>Delete project?</AlertDialogTitle> <AlertDialogDescription>This permanently removes the project and cannot be undone.</AlertDialogDescription> </AlertDialogHeader> <AlertDialogBody> <Field label={`Type “${projectName}” to confirm`} description="The project name is case-sensitive."> <Input autoComplete="off" value={confirmation} onChange={(event) => setConfirmation(event.target.value)} /> </Field> </AlertDialogBody> <AlertDialogFooter> <AlertDialogCancel ref={cancelRef} render={<Button variant="secondary">Cancel</Button>} /> <AlertDialogAction disabled={!isConfirmed} render={<Button variant="danger" onClick={deleteProject}>Delete project</Button>} /> </AlertDialogFooter> </AlertDialogContent> </AlertDialogPortal> </AlertDialog> );}Installation and imports
Install the editable registry source, or use the matching package entrypoint when the product keeps Nerio as a workspace dependency.
pnpm exec nerio add alert-dialogimport * as React from 'react';import { AlertDialog, AlertDialogAction, AlertDialogBackdrop, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogPortal, AlertDialogTitle, AlertDialogTrigger, Button } from '@nerio-ui/ui/client';Usage
import * as React from 'react';import { AlertDialog, AlertDialogAction, AlertDialogBackdrop, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogPortal, AlertDialogTitle, AlertDialogTrigger, Button } from '@nerio-ui/ui/client';function DeleteProjectDialog() { const cancelRef = React.useRef<HTMLButtonElement>(null); return ( <AlertDialog> <AlertDialogTrigger render={<Button variant="danger">Delete project</Button>} /> <AlertDialogPortal> <AlertDialogBackdrop /> <AlertDialogContent initialFocus={cancelRef}> <AlertDialogHeader> <AlertDialogTitle>Delete project?</AlertDialogTitle> <AlertDialogDescription>This permanently removes the project and cannot be undone.</AlertDialogDescription> </AlertDialogHeader> <AlertDialogFooter> <AlertDialogCancel ref={cancelRef} render={<Button variant="secondary">Cancel</Button>} /> <AlertDialogAction render={<Button variant="danger" onClick={deleteProject}>Delete project</Button>} /> </AlertDialogFooter> </AlertDialogContent> </AlertDialogPortal> </AlertDialog> );}Variants
| Variant | Purpose |
|---|---|
Confirmation | One explicit cancel/action decision. |
Anatomy
| Slot | Purpose |
|---|---|
portal | Container boundary for the portalled confirmation. |
trigger | Control that requests the confirmation. |
backdrop | Modal backdrop that does not dismiss on pointer press. |
content | Viewport-bounded alertdialog surface with deliberate focus. |
header | Groups the accessible name and concrete consequence. |
title | Required accessible name phrased as the decision. |
description | Explains the consequence without ambiguous language. |
body | Optional supporting content; keep the decision concise. |
footer | Action row with cancel before confirmation. |
cancel | Safe response and recommended initial-focus target. |
action | Explicit confirmation boundary that closes after the consumer handler runs. |
States
| State | Purpose |
|---|---|
Open | Pointer dismissal is disabled and focus stays in the alertdialog. |
Cancelled | The safe response closes and restores focus. |
Confirmed | The consumer handler runs and the dialog closes. |
Motion
- overlay entry and exit
- reduced-motion fade-only state change
Accessibility
- Uses the Base UI Alert Dialog primitive with role=alertdialog, modal focus containment, Escape dismissal, scroll locking, and pointer dismissal disabled.
- AlertDialogTitle provides the accessible name and AlertDialogDescription explains the consequence in concrete language.
- Place AlertDialogCancel before AlertDialogAction and pass its ref to AlertDialogContent initialFocus for destructive or difficult-to-reverse actions.
- AlertDialogCancel and AlertDialogAction are explicit close boundaries; mutation, async orchestration, permissions, routing, and confirmation copy remain consumer-owned.
- Focus returns to the trigger after either response and every action keeps native Button keyboard semantics through render composition.
Review the shared responsibility and evidence boundaries in the Accessibility foundation alongside this component-specific contract. Use the Spacing & layout foundation for shared density, wrapping, overflow, reflow, and component-versus-product ownership guidance. The Color foundation, Typography foundation, and Localization foundation define the shared visual-role, text-resilience, direction, and locale boundaries used by component examples.
API
| Prop | Purpose |
|---|---|
AlertDialog | Controlled or uncontrolled Base UI Alert Dialog root. |
AlertDialogContent | Accepts initialFocus, finalFocus, className, native popup props, and a forwarded ref. |
AlertDialogCancel | Explicit safe close boundary and recommended initial-focus target. |
AlertDialogAction | Explicit confirm close boundary; consumers attach mutation behavior to the rendered Button. |
Implementation contract
| Contract | Value |
|---|---|
Registry item | alert-dialog installs 1 source file into the configured components directory. |
Base UI | alert-dialog |
Registry dependencies | dialog |
Package dependencies | @base-ui/react, clsx, react, tailwind-merge, tailwindcss |
Styling contract
| Contract | Value |
|---|---|
Authoring | Complete, statically detectable Tailwind CSS v4 recipes own component visuals. |
Values | Semantic and component --n-* variables remain the canonical customization layer. |
Overrides | Customizable slots merge consumer className values with tailwindCn so conflicting utilities resolve deterministically. |
Residual CSS | Only shared keyframes and scoped no-Preflight compatibility rules remain; there is no parallel visual selector layer. |
Design notes
- AlertDialog is a response boundary, not an async mutation orchestrator.
- Exact-name confirmation is optional consumer-owned policy composed inside AlertDialogBody.
- A normal Dialog remains appropriate for reversible tasks and forms with their own completion model.
Do / do not
Name the action and consequence precisely, focus Cancel first, and keep one clear confirmation action.
Compose an exact entity-name confirmation when consumer product policy requires it.
Do not hide side effects, default focus to a destructive action, or put multi-step workflows in AlertDialog.
Related components
Tokens
These are the primary customization points. Override semantic or component tokens instead of changing component source.
| Token | Purpose |
|---|---|
--n-dialog-width-md | Public customization point for this component contract. |
--n-dialog-viewport-inset | Public customization point for this component contract. |
--n-dialog-padding | Public customization point for this component contract. |
--n-dialog-header-gap | Public customization point for this component contract. |
--n-dialog-header-margin | Public customization point for this component contract. |
--n-dialog-body-gap | Public customization point for this component contract. |
--n-overlay-z-index | Public customization point for this component contract. |
--n-overlay-background | Public customization point for this component contract. |
--n-overlay-border | Public customization point for this component contract. |
--n-overlay-backdrop | Public customization point for this component contract. |
--n-overlay-backdrop-filter | Public customization point for this component contract. |
--n-overlay-foreground | Public customization point for this component contract. |
--n-overlay-foreground-muted | Public customization point for this component contract. |
--n-overlay-control-background | Public customization point for this component contract. |
--n-overlay-control-background-hover | Public customization point for this component contract. |
--n-overlay-surface-filter | Public customization point for this component contract. |
--n-overlay-shadow | Public customization point for this component contract. |
--n-motion-overlay-enter-duration | Public customization point for this component contract. |
--n-motion-overlay-enter-easing | Public customization point for this component contract. |
--n-motion-overlay-exit-duration | Public customization point for this component contract. |
--n-motion-overlay-exit-easing | Public customization point for this component contract. |
--n-focus-ring | Public customization point for this component contract. |