AlertDialog

A modal confirmation that requires a response. It does not close on outside press and focuses Cancel first.

Import

tsx
import { AlertDialog } from "@merid/react";

Anatomy

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

Root, Trigger, Title, Description and Footer are the same parts as Dialog. Cancel is a secondary Button that dismisses and receives initial focus; Action is a primary (or tone="danger") Button that confirms and closes. There is no icon close button.

Examples

Destructive confirmation

The example above is the canonical use: name the object, state the consequence, and repeat the verb on the Action button.

Keeping the dialog open while working

Call event.preventDefault() in the Action's onClick to keep the dialog open, then close it yourself with controlled state once the work finishes.

tsx
const [open, setOpen] = useState(false);

<AlertDialog.Root open={open} onOpenChange={setOpen}>
  <AlertDialog.Content>
    <AlertDialog.Title>Delete project?</AlertDialog.Title>
    <AlertDialog.Footer>
      <AlertDialog.Cancel>Cancel</AlertDialog.Cancel>
      <AlertDialog.Action
        onClick={async (event) => {
          event.preventDefault();
          await deleteProject();
          setOpen(false);
        }}
      >
        Delete
      </AlertDialog.Action>
    </AlertDialog.Footer>
  </AlertDialog.Content>
</AlertDialog.Root>

API reference

AlertDialog.Root

PropTypeDefaultDescription
openboolean–Controlled open state.
defaultOpenbooleanfalseInitial open state when uncontrolled.
onOpenChange(open: boolean) => void–Called when the open state should change.
childrenReactNode–Trigger, Content and anything else sharing this dialog's state.

AlertDialog.Content

Accepts every <div> attribute except role. Outside press never closes it.

PropTypeDefaultDescription
closeOnEscapebooleantrueClose on Escape.
initialFocusRefObject<HTMLElement | null>–Element to focus when opened; defaults to [data-autofocus] (the Cancel button), then the first tabbable element.
containerElement | nulldocument.bodyPortal target. `undefined` uses `document.body`; `null` renders nothing until the target exists.
showClosebooleanfalseRender the standard top-right icon close button automatically. Skipped while you render your own icon `Close`.
closeLabelstring"Close"Accessible name of the automatic close button.
refRef<HTMLDivElement>–Forwarded ref to the dialog element.

AlertDialog.Action

Accepts every <button> attribute. Renders a Button styled by tone. Closes on click unless the handler calls event.preventDefault().

PropTypeDefaultDescription
toneAlertDialogActionTone"primary"Button style: `primary`, or `danger` for destructive actions. `AlertDialogActionTone` is `"primary" | "danger"`.
asChildbooleanfalseRender the single child element (e.g. your own `Button`) instead of a `<button>`, merging props, ref and handlers.
refRef<HTMLButtonElement>–Forwarded ref to the button.

AlertDialog.Cancel

Accepts every <button> attribute. Renders a secondary Button and carries data-autofocus, so it receives initial focus.

PropTypeDefaultDescription
asChildbooleanfalseRender the single child element (e.g. your own `Button`) instead of a `<button>`, merging props, ref and handlers.
refRef<HTMLButtonElement>–Forwarded ref to the button.

Trigger (including asChild), Title, Description and Footer take the same props as their Dialog counterparts.

Styling

AlertDialog reuses the dialog classes (.mrd-dialog__backdrop, .mrd-dialog, .mrd-dialog__title, .mrd-dialog__description, .mrd-dialog__footer). The surface carries data-kind="alert", which narrows it to 440px, and data-state="open" while mounted. Cancel renders as .mrd-button with data-variant="secondary"; Action as .mrd-button with data-variant set from tone. AlertDialog.Content has no size prop.

Accessibility

Follows the WAI-ARIA Alert and Message Dialogs pattern. Content has role="alertdialog", aria-modal="true" and is labelled by the Title and described by the Description.

KeyAction
SpaceEnterOn the trigger, opens the dialog; focus moves to Cancel.
TabMoves between Cancel, Action and other controls, wrapping inside the dialog.
ShiftTabMoves focus backwards, wrapping inside the dialog.
EscDismisses, like Cancel, and returns focus to the trigger.

Guidelines

Do

Say exactly what will happen and repeat the verb on the Action: “Delete project”.

Avoid

Ask “Are you sure?” with Yes and No buttons.

Do

Reserve alert dialogs for destructive or irreversible actions.

Avoid

Confirm routine actions that can be undone; show a toast with Undo instead.
  • Dialog for tasks that are not confirmations.
  • Toast for undoable feedback.