Skip to main content

Alert Dialog

A modal dialog for critical confirmations that requires user action. Built on Base UI AlertDialog primitive with accessibility features like focus trapping and Escape key handling disabled by default.

Compound Components

AlertDialog.Root

The root container that manages alert dialog state.
open
boolean
Controlled open state. When provided, the dialog becomes controlled.
defaultOpen
boolean
default:"false"
Uncontrolled default open state.
onOpenChange
(open: boolean, eventDetails: object) => void
Callback fired when the open state changes.
modal
boolean
default:"true"
Whether the dialog is modal (blocks interaction with the rest of the page).

AlertDialog.Trigger

The trigger element that opens the alert dialog.
className
string
Additional CSS classes to apply.
asChild
boolean
default:"false"
Merge props onto the child element instead of rendering a button.

AlertDialog.Portal

Portals the alert dialog content to the end of the document body.
keepMounted
boolean
default:"false"
Whether to keep the dialog mounted in the DOM when closed. When false, uses AnimatePresence for mount/unmount animations.
container
HTMLElement | null
The container element to portal into. Defaults to document.body.

AlertDialog.Backdrop

The backdrop overlay behind the alert dialog.
className
string
Additional CSS classes to apply. Default: "fixed inset-0 z-50 bg-utility-backdrop"
Animation: Fades in/out with spring transition (bounce: 0, duration: 0.15s). Respects reduced motion preferences.

AlertDialog.Popup

The alert dialog popup container with positioning and animation.
className
string
Additional CSS classes to apply.
Responsive Behavior:
  • Mobile (< 640px): Bottom sheet with 8px padding
  • Desktop: Centered modal, max-width 400px
Animation:
  • Mobile: Slides up from bottom
  • Desktop: Scale from 0.95 to 1 with fade
  • Respects reduced motion preferences

AlertDialog.Content

Inner content area with optional icon, title, and description.
icon
React.ReactNode
Optional icon to display above the title.
iconTone
'default' | 'danger' | 'warning' | 'info' | 'success'
default:"'default'"
Color tone for the icon:
  • default: Content strong color
  • danger: Danger feedback color
  • warning: Warning feedback color
  • info: Info feedback color
  • success: Success feedback color
className
string
Additional CSS classes to apply.
Layout: Centered content with 24px padding and 24px gap between elements.

AlertDialog.Title

Accessible alert dialog title.
className
string
Additional CSS classes to apply. Default: Large semibold text with strong content color.

AlertDialog.Description

Accessible alert dialog description.
className
string
Additional CSS classes to apply. Default: Medium text with subtle content color.

AlertDialog.Close

Close button wrapper. Must wrap a Button component.
className
string
Additional CSS classes to apply. Default: "outline-none flex-1"
asChild
boolean
default:"false"
Merge props onto the child element.
Footer section for action buttons.
className
string
Additional CSS classes to apply.
Layout:
  • All buttons fill available width equally
  • 12px gap between buttons
  • Padding: 16px vertical, 24px horizontal

Usage

import { AlertDialog } from '@soft-ui/react/alert-dialog'
import { Button } from '@soft-ui/react/button'
import { RiAlertFill } from '@soft-ui/icons'

function DeleteConfirmation() {
  return (
    <AlertDialog.Root>
      <AlertDialog.Trigger asChild>
        <Button variant="danger">Delete Account</Button>
      </AlertDialog.Trigger>
      <AlertDialog.Portal>
        <AlertDialog.Backdrop />
        <AlertDialog.Popup>
          <AlertDialog.Content icon={<RiAlertFill />} iconTone="danger">
            <AlertDialog.Title>Delete Account</AlertDialog.Title>
            <AlertDialog.Description>
              Are you sure you want to delete your account? This action cannot be undone.
            </AlertDialog.Description>
          </AlertDialog.Content>
          <AlertDialog.Footer>
            <AlertDialog.Close asChild>
              <Button variant="secondary">Cancel</Button>
            </AlertDialog.Close>
            <Button variant="danger">Delete</Button>
          </AlertDialog.Footer>
        </AlertDialog.Popup>
      </AlertDialog.Portal>
    </AlertDialog.Root>
  )
}

Icon Tones

// Danger alert
<AlertDialog.Content icon={<RiErrorWarningFill />} iconTone="danger">
  <AlertDialog.Title>Error</AlertDialog.Title>
  <AlertDialog.Description>Something went wrong.</AlertDialog.Description>
</AlertDialog.Content>

// Warning alert
<AlertDialog.Content icon={<RiAlertFill />} iconTone="warning">
  <AlertDialog.Title>Warning</AlertDialog.Title>
  <AlertDialog.Description>Proceed with caution.</AlertDialog.Description>
</AlertDialog.Content>

// Success alert
<AlertDialog.Content icon={<RiCheckboxCircleFill />} iconTone="success">
  <AlertDialog.Title>Success</AlertDialog.Title>
  <AlertDialog.Description>Operation completed.</AlertDialog.Description>
</AlertDialog.Content>

Types

export type AlertDialogRootProps = {
  open?: boolean
  defaultOpen?: boolean
  onOpenChange?: (open: boolean, eventDetails: object) => void
  modal?: boolean
  children?: React.ReactNode
}

export type AlertDialogContentProps = {
  icon?: React.ReactNode
  iconTone?: 'default' | 'danger' | 'warning' | 'info' | 'success'
  className?: string
  children?: React.ReactNode
}

Accessibility

  • Focus is trapped within the dialog when open
  • Escape key is disabled by default (use explicit Close buttons)
  • Backdrop click is disabled by default
  • Title and description are linked via aria-labelledby and aria-describedby
  • First focusable element receives focus on open

Build docs developers (and LLMs) love