Alert Dialog
Modal alert dialog behavior for urgent confirmations and decisions that require an answer before the user can continue.
Alert Dialog in motion
When to Use
Use AlertDialog when the user must stop and make an important choice, such as
confirming a destructive action or acknowledging a serious consequence. Use
Dialog for ordinary forms, settings, and information that does not require an
urgent decision.
Features
The behavior Atom owns before your product adds appearance.
- Forces
role="alertdialog"on Content. - Prevents backdrop-click dismissal by design.
- Supports controlled and uncontrolled open state.
- Autofocuses Cancel by default so the safer choice receives initial focus.
- Reports action, cancel, and Escape close reasons.
- Traps focus, restores focus, handles Escape, and locks document scrolling.
- Uses stack-aware Escape dismissal so nested overlays close first.
- Supports optional portals and keep-mounted content.
Import
Anatomy
API Reference
Root
Owns the alert dialog's open state and close policy. Root renders no DOM element; it provides state and generated IDs to the other parts.
| Prop | Type | Default |
|---|---|---|
open | boolean | - |
defaultOpen | boolean | false |
onOpenChange | (open: boolean, reason?: AlertDialogCloseReason) => void | - |
closeOnEscape | boolean | true |
disabled | boolean | false |
keepMounted | boolean | false |
Backdrop dismissal is always disabled and is not exposed as a Root prop.
Trigger
Opens the alert dialog and stores the element used for focus restoration. It
renders a native button by default and accepts native button props.
| Prop | Type | Default |
|---|---|---|
asChild | boolean | false |
render | RenderProp | - |
| ARIA attribute | Values |
|---|---|
role | "button" for custom renders |
aria-haspopup | "dialog" |
aria-expanded | "true" | "false" |
aria-controls | Content ID while open |
aria-disabled | "true" when Root is disabled |
| Data attribute | Values |
|---|---|
[data-slot] | "alert-dialog-trigger" |
[data-state] | "open" | "closed" |
[data-disabled] | Present when Root is disabled |
Portal
Moves its children to document.body after mounting, or to a supplied
container. Set disabled to render the children in place.
| Prop | Type | Default |
|---|---|---|
container | HTMLElement | null | document.body |
disabled | boolean | false |
The container must be an HTMLElement in the current document. ShadowRoot,
DocumentFragment, and cross-document containers are unsupported. Atom keeps
the ancestor paths to separate Overlay and Content portals, inline Content,
nested same-document containers, and registered branches active while making
background subtrees inert. Global Toast/live-region containers are background
unless they are within an owned path or registered with Modal.Branch.
Portal renders no wrapper element.
Overlay
Renders the assistive-technology-hidden backdrop while the alert dialog is
present. Clicking it never closes an AlertDialog.
Overlay and Content must remain siblings; Atom rejects Content nested beneath
the Overlay's aria-hidden subtree.
Separate portals are valid when the committed Content DOM is outside Overlay.
| Prop | Type | Default |
|---|---|---|
disabled | boolean | false |
| ARIA attribute | Values |
|---|---|
aria-hidden | "true" |
| Data attribute | Values |
|---|---|
[data-slot] | "alert-dialog-overlay" |
[data-state] | "open" | "closed" |
[data-positioned] | Present after the first positioning frame |
Content
Renders the modal alert dialog panel, traps focus while open, restores focus on close, and supplies the generated title and description relationships.
| Prop | Type | Default |
|---|---|---|
aria-label | string | - |
aria-labelledby | string | generated from Title when present |
aria-describedby | string | undefined | generated from Description when present |
ariaLabel | string | compatibility fallback |
initialFocus | ModalFocusTarget<ModalInitialFocusDetails> | Cancel through native autoFocus |
finalFocus | ModalFocusTarget<ModalFinalFocusDetails> | prior focus, then Trigger |
| ARIA attribute | Values |
|---|---|
role | "alertdialog" |
aria-modal | "true" while open |
aria-hidden | "true" while retained only for exit presence |
inert | Present while retained only for exit presence |
aria-labelledby | Explicit native value, otherwise registered Title ID |
aria-label | Explicit native value, otherwise ariaLabel compatibility value |
aria-describedby | Explicit native value, otherwise registered Description ID |
| Data attribute | Values |
|---|---|
[data-slot] | "alert-dialog-content" |
[data-state] | "open" | "closed" |
[data-positioned] | Present after the first positioning frame |
Exit-animated Content retained after close immediately loses aria-modal and
becomes inert and accessibility-hidden while the visual exit completes.
Background isolation, focus ownership, and active scroll containment end when
open becomes false.
Title
Renders the visible heading that names Content. It receives the generated ID
referenced by aria-labelledby and renders an h2 by default.
| Prop | Type | Default |
|---|---|---|
as | "h1" | "h2" | "h3" | "h4" | "h5" | "h6" | "h2" |
| Data attribute | Values |
|---|---|
[data-slot] | "alert-dialog-title" |
Description
Renders a p that explains the consequence or decision. It receives the
generated ID referenced by Content's aria-describedby.
Alert dialogs require an accessible description. Atom warns during development
after registration settles when neither Description nor native
aria-describedby is present. Native ARIA is preferred and takes precedence;
ariaLabel remains supported only for compatibility.
Consumer-owned third-party portals must either wrap their top-level element in
<Modal.Branch asChild> or target the AlertDialog Content element as their
portal container. Nested modal layers suspend the parent while the child is
topmost, including focus trapping, Escape handling, and scroll containment.
Cancel's native autoFocus remains the safe initial-focus default for keyboard
and pointer opening, including touch. An explicit initialFocus target takes
precedence. Use finalFocus for a different post-decision workflow target. Its
details describe the closing interaction and include actionClick,
cancelClick, or escapeKeyDown as applicable.
| Data attribute | Values |
|---|---|
[data-slot] | "alert-dialog-description" |
Cancel
Renders the safer control, closes with reason: "cancelClick", and receives
initial focus by default. It renders a native button unless composed.
| Prop | Type | Default |
|---|---|---|
asChild | boolean | false |
render | RenderProp | - |
autoFocus | boolean | true |
| Data attribute | Values |
|---|---|
[data-slot] | "alert-dialog-cancel" |
Action
Renders the confirmation control and closes with reason: "actionClick" after
its consumer click handler runs. It renders a native button unless composed.
| Prop | Type | Default |
|---|---|---|
asChild | boolean | false |
render | RenderProp | - |
| Data attribute | Values |
|---|---|
[data-slot] | "alert-dialog-action" |
Examples
Destructive Confirmation
Track the Decision
Accessibility
AlertDialog follows the
WAI-ARIA Alert Dialog pattern.
Content has role="alertdialog" and aria-modal="true". Provide a Title or an
ariaLabel, and always provide a Description that clearly explains the
consequence. Cancel receives initial focus by default so destructive dialogs do
not place focus on the destructive action.
Focus stays inside the open dialog and returns to the Trigger after closing. Backdrop clicks do not dismiss the dialog.
| Key | Description |
|---|---|
Escape | Closes the alert dialog when closeOnEscape is enabled. |
Tab | Moves to the next focusable element, wrapping inside Content. |
Shift+Tab | Moves to the previous focusable element, wrapping inside Content. |
Changelog
Unreleased
0.24.0
- Added public Agent Knowledge for component selection, required composition, recurring mistakes, and validation.
0.20.3
- Inherited document-only overflow locking so sticky application chrome remains anchored while AlertDialog is open at a nonzero page scroll position.
0.6.7
- Inherited root/body overflow locking without fixed-body repositioning or unlock-time scroll restoration, avoiding iOS Safari browser-toolbar transitions.
0.3.4
- Inherited corrected scroll-lock compensation so opening or closing AlertDialog no longer shifts pages that preserve their scrollbar gutter.
0.3.2
- Inherited corrected nested-modal isolation handoff and final
inertrestoration from the shared Modal foundation.
0.3.1
- Inherited reliable exit-presence cleanup so closed AlertDialog Content and Overlay cannot remain above the page when CSS emits no end event.
0.3.0
- Fixed native Content ARIA precedence and registered Title/Description relationships across SSR and hydration.
- Added a settled development warning when an alert dialog lacks its required accessible description.
- Added Content-level
initialFocusandfinalFocuswhile preserving Cancel's native safe autofocus default. - Added shared top-layer ownership and
Modal.Branchsupport for third-party alert-dialog portals. - Preserved descendant composite and nested-modal keyboard contracts through metadata-aware focus containment.
- Added registered-portal scroll allowances and per-document wheel/touch background containment with exact cleanup.
- Added stack-aware background isolation and same-document
HTMLElementportal-container enforcement through the shared Modal foundation. - Established shared modal ownership before paint and made exit-present Content inert and accessibility-hidden with uninterrupted nested lock handoff.
- Rejected Content nested beneath the accessibility-hidden Overlay.
0.2.0
- Added shared dismissable layer Escape handling so nested overlays close before the parent alert dialog closes.
- Improved modal focus containment, including support for registered portalled layers owned by descendants inside the alert dialog.
0.1.0
- Initial Atom release.