AlertDialog

A modal dialog that asks a question. Same <dialog> and same top layer as Dialog, with role="alertdialog" and a different set of buttons.

import { AlertDialog } from '@apostel/bedrock'
// or, for a veto: import { AlertDialog } from '@apostel/bedrock/controlled'
Loading demo…
Source
import { useState } from 'react'
import { AlertDialog } from '../../src/index'

/**
 * The same `<dialog>` as Dialog, with `role="alertdialog"` and no close button
 * — an alert dialog asks a question, so both ways out are answers. Escape still
 * works, because taking it away would trap a keyboard user in a decision.
 */
export default function AlertDialogDemo() {
  const [result, setResult] = useState('')

  return (
    <>
      <AlertDialog.Root>
        <AlertDialog.Trigger>Delete project</AlertDialog.Trigger>
        <AlertDialog.Content>
          <AlertDialog.Title>Delete this project?</AlertDialog.Title>
          <AlertDialog.Description>
            Every deployment and log goes with it. This cannot be undone.
          </AlertDialog.Description>
          <AlertDialog.Cancel onClick={() => setResult('cancelled')}>Keep it</AlertDialog.Cancel>{' '}
          <AlertDialog.Action onClick={() => setResult('deleted')}>Delete</AlertDialog.Action>
        </AlertDialog.Content>
      </AlertDialog.Root>
      {result ? <output>{result}</output> : null}
    </>
  )
}

Anatomy

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

Root, Trigger, Title and Description are Dialog's parts — the same components, re-exported, because they behave identically. Only Content, Cancel and Action differ.

AlertDialog.Content

Renders <dialog role="alertdialog">. Otherwise identical to Dialog.Content: children mount only while open, aria-labelledby and aria-describedby are wired to the title and description, and id is not forwarded.

role="alertdialog" tells a screen reader to announce the whole dialog immediately rather than just move focus into it, which is the behaviour a destructive confirmation wants.

AlertDialog.Cancel / AlertDialog.Action

Both render <button>. Cancel closes with request-close, the same as Dialog.Close; Action runs your handler and closes.

There is no AlertDialog.Close. An alert dialog asks a question, so both ways out are answers — a third, meaningless dismissal would leave the caller not knowing what the user decided.

Escape still closes, and deliberately so. Removing it would trap a keyboard user in a decision, and every platform's own alert dialogs allow it. Escape is a cancel: treat it as one.

What is not here