Components

AlertDialog

Modal alert dialog behavior for urgent confirmations and decisions that require an answer before the user can continue.

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

  • 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

import { AlertDialog } from "@flowstack-ui/atom";

Anatomy

<AlertDialog.Root>
  <AlertDialog.Trigger />
  <AlertDialog.Portal>
    <AlertDialog.Overlay />
    <AlertDialog.Content>
      <AlertDialog.Title />
      <AlertDialog.Description />
      <AlertDialog.Cancel />
      <AlertDialog.Action />
    </AlertDialog.Content>
  </AlertDialog.Portal>
</AlertDialog.Root>

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.

PropTypeDefault
openboolean-
defaultOpenbooleanfalse
onOpenChange(open: boolean, reason?: AlertDialogCloseReason) => void-
closeOnEscapebooleantrue
disabledbooleanfalse
keepMountedbooleanfalse

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.

PropTypeDefault
asChildbooleanfalse
renderRenderProp-
ARIA attributeValues
role"button" for custom renders
aria-haspopup"dialog"
aria-expanded"true" | "false"
aria-controlsContent ID while open
aria-disabled"true" when Root is disabled
Data attributeValues
[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.

PropTypeDefault
containerElement | DocumentFragment | nulldocument.body
disabledbooleanfalse

Portal renders no wrapper element.

Overlay

Renders the assistive-technology-hidden backdrop while the alert dialog is present. Clicking it never closes an AlertDialog.

PropTypeDefault
disabledbooleanfalse
ARIA attributeValues
aria-hidden"true"
Data attributeValues
[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.

PropTypeDefault
ariaLabelstring-
ARIA attributeValues
role"alertdialog"
aria-modal"true" while visible
aria-labelledbyGenerated Title ID when ariaLabel is not provided
aria-labelValue from ariaLabel when provided
aria-describedbyGenerated Description ID
Data attributeValues
[data-slot]"alert-dialog-content"
[data-state]"open" | "closed"
[data-positioned]Present after the first positioning frame

Title

Renders the visible heading that names Content. It receives the generated ID referenced by aria-labelledby and renders an h2 by default.

PropTypeDefault
as"h1" | "h2" | "h3" | "h4" | "h5" | "h6""h2"
Data attributeValues
[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.

Data attributeValues
[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.

PropTypeDefault
asChildbooleanfalse
renderRenderProp-
autoFocusbooleantrue
Data attributeValues
[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.

PropTypeDefault
asChildbooleanfalse
renderRenderProp-
Data attributeValues
[data-slot]"alert-dialog-action"

Examples

Destructive Confirmation

import { AlertDialog } from "@flowstack-ui/atom";

export function DeleteProjectDialog() {
  return (
    <AlertDialog.Root>
      <AlertDialog.Trigger>Delete project</AlertDialog.Trigger>
      <AlertDialog.Portal>
        <AlertDialog.Overlay />
        <AlertDialog.Content>
          <AlertDialog.Title>Delete project?</AlertDialog.Title>
          <AlertDialog.Description>
            This permanently removes the project and cannot be undone.
          </AlertDialog.Description>
          <AlertDialog.Cancel>Keep project</AlertDialog.Cancel>
          <AlertDialog.Action>Delete project</AlertDialog.Action>
        </AlertDialog.Content>
      </AlertDialog.Portal>
    </AlertDialog.Root>
  );
}

Track the Decision

import { AlertDialog } from "@flowstack-ui/atom";

export function TrackedAlertDialog() {
  return (
    <AlertDialog.Root
      onOpenChange={(open, reason) => {
        if (!open) {
          console.log(`Alert dialog closed: ${reason ?? "unknown"}`);
        }
      }}
    >
      <AlertDialog.Trigger>Reset settings</AlertDialog.Trigger>
      <AlertDialog.Content>
        <AlertDialog.Title>Reset every setting?</AlertDialog.Title>
        <AlertDialog.Description>
          Your preferences will return to their original values.
        </AlertDialog.Description>
        <AlertDialog.Cancel>Cancel</AlertDialog.Cancel>
        <AlertDialog.Action>Reset settings</AlertDialog.Action>
      </AlertDialog.Content>
    </AlertDialog.Root>
  );
}

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.

KeyDescription
EscapeCloses the alert dialog when closeOnEscape is enabled.
TabMoves to the next focusable element, wrapping inside Content.
Shift+TabMoves to the previous focusable element, wrapping inside Content.

Changelog

See CHANGELOG.md.