# AlertDialog

> A small centered dialog that asks people to confirm an action that cannot be undone or that interrupts work, with a confirm button colored by the consequence.

Source: https://raft-design.botiverse.build/components/alert-dialog. Generated from the current release; where it differs from what you remember, this page is right.

An alert dialog asks people to confirm an action before it happens, when the action cannot be undone (delete) or interrupts work (stop, reset). It is a 400px dialog on a scrim with a title, a sentence on what will happen, Cancel and a confirm button whose color states the consequence.

```tsx
import {
  AlertDialog,
  AlertDialogAction,
  AlertDialogBody,
  AlertDialogCancel,
  AlertDialogClose,
  AlertDialogContent,
  AlertDialogFooter,
  AlertDialogHeader,
  AlertDialogTitle,
} from "@botiverse/raft-ui";

function ConfirmActionAlertDialogParts() {
  return (
    <>
      <AlertDialogHeader>
        <AlertDialogTitle>Delete Task</AlertDialogTitle>
        <AlertDialogClose />
      </AlertDialogHeader>
      <AlertDialogBody>
        <p className="m-0 text-sm leading-5 text-foreground/60">
          Delete task <strong className="font-bold text-foreground">#42</strong>{" "}
          <strong className="font-bold text-foreground">"Review dialog migration"</strong>? This
          cannot be undone.
        </p>
      </AlertDialogBody>
      <AlertDialogFooter>
        <AlertDialogCancel size="md">Cancel</AlertDialogCancel>
        <AlertDialogAction variant="danger" size="md">
          Delete Task
        </AlertDialogAction>
      </AlertDialogFooter>
    </>
  );
}

export function ConfirmActionAlertDialogContent() {
  return (
    <AlertDialogContent>
      <ConfirmActionAlertDialogParts />
    </AlertDialogContent>
  );
}
```

## When to use

| Situation                                                                                       | Use                                                                                                                                     |
| ----------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------- |
| An action that cannot be undone: delete a message, an agent, a server                           | AlertDialog, red                                                                                                                        |
| An action that interrupts but can be recovered: stop an agent, reset a session, leave a channel | AlertDialog, orange                                                                                                                     |
| An action that can be reversed in place                                                         | No dialog: do it; when a [Toast](https://raft-design.botiverse.build/components/toast.md) offers Undo is in [Feedback](https://raft-design.botiverse.build/patterns/feedback.md#confirming) |
| A decision that needs more than the name typed                                                  | [Dialog](https://raft-design.botiverse.build/components/dialog.md)                                                                                                           |

## Anatomy

- `AlertDialog`: the root. Required.
- `AlertDialogTrigger`: the button that opens it. Usually the dialog is opened from a menu item instead.
- `AlertDialogContent`: the centered surface, at most 400px wide, the width of a `size="sm"` [Dialog](https://raft-design.botiverse.build/components/dialog.md#variants), so every confirmation is one width, with the scrim (`AlertDialogOverlay`) behind it. Required.
- `AlertDialogHeader`: the title row, with an optional `AlertDialogClose` (×).
- `AlertDialogTitle`: the title. Required.
- `AlertDialogBody` and `AlertDialogDescription`: what will happen.
- `AlertDialogFooter`: the buttons, aligned to the end.
- `AlertDialogCancel`: a ghost button that closes the dialog. Required.
- `AlertDialogAction`: the confirm button. It is a Button and doesn't close the dialog by itself: close it when the action finishes.
- `AlertDialogPortal`: a lower-level part.

## Variants

The confirm button's color says what happens:

| Consequence                      | Confirm button                                                                                  | Example      |
| -------------------------------- | ----------------------------------------------------------------------------------------------- | ------------ |
| Does something                   | `variant="primary"`                                                                             | Make Public  |
| Interrupts, but can be recovered | `variant="warning"`                                                                             | Stop         |
| Cannot be undone                 | `variant="danger"`, and a [Banner](https://raft-design.botiverse.build/components/banner.md) with `status="destructive"` in the body | Delete Agent |

Deleting something large, such as an agent or a server, also asks for its name to be typed ([Forms](https://raft-design.botiverse.build/patterns/forms.md#danger-zone)):

```tsx
import {
  AlertDialog,
  AlertDialogAction,
  AlertDialogBody,
  AlertDialogCancel,
  AlertDialogClose,
  AlertDialogContent,
  AlertDialogFooter,
  AlertDialogHeader,
  AlertDialogTitle,
} from "@botiverse/raft-ui";
import { Field, FieldLabel, InlineCode, Input } from "@botiverse/raft-ui";

function TypedDeleteAlertDialogParts() {
  return (
    <>
      <AlertDialogHeader>
        <AlertDialogTitle>Delete Server</AlertDialogTitle>
        <AlertDialogClose />
      </AlertDialogHeader>
      <AlertDialogBody className="grid gap-5">
        <p className="m-0 text-sm leading-5 text-foreground/60">
          This will permanently delete <strong className="font-bold text-foreground">Raft</strong>{" "}
          and all its data (agents, channels, messages). This cannot be undone.
        </p>
        <Field>
          <FieldLabel htmlFor="alert-dialog-delete-server">
            Type <InlineCode>raft</InlineCode> to confirm:
          </FieldLabel>
          <Input
            id="alert-dialog-delete-server"
            placeholder="raft"
            className="font-mono"
            suppressPasswordManager
          />
        </Field>
      </AlertDialogBody>
      <AlertDialogFooter>
        <AlertDialogCancel size="md">Cancel</AlertDialogCancel>
        <AlertDialogAction variant="danger" size="md">
          Delete Server
        </AlertDialogAction>
      </AlertDialogFooter>
    </>
  );
}

export function TypedDeleteAlertDialogContent() {
  return (
    <AlertDialogContent>
      <TypedDeleteAlertDialogParts />
    </AlertDialogContent>
  );
}
```

## Behavior

- It appears and disappears without animation, over the scrim, like every centered dialog ([Dialog](https://raft-design.botiverse.build/components/dialog.md#behavior)).
- Esc and Cancel close it without acting.

## Content

- Title it with the action and the thing it acts on, as a question: Delete Box?
- Say in one or two sentences what happens, in plain words: "Box leaves every channel."
- Label the confirm button with the title's verb: Stop for Stop Wug?. Keep the object when it can't be undone, on the red button: Delete Agent. Label the other button Cancel ([Writing](https://raft-design.botiverse.build/content/writing.md#actions-and-their-dialogs)).

## Accessibility

- AlertDialog wraps the Base UI Dialog and sets the `alertdialog` role, so screen readers announce it as an interruption. Base UI provides the focus trap, Esc and focus return.
- `AlertDialogTitle` is the accessible name and `AlertDialogDescription` the description. Put the consequence in `AlertDialogDescription`, so it is announced with the title.
- The × of `AlertDialogClose` is labeled "Close".

## Rules

- Put Cancel on the left and the confirm button on the right, and no other buttons.
- Don't color the menu item that opens the dialog: the confirm button carries the color ([Feedback](https://raft-design.botiverse.build/patterns/feedback.md#confirming)).

## API

### AlertDialog

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `actionsRef` | `RefObject<DialogRootActions \| null>` |  | A ref to imperative actions. - `unmount`: Manually unmounts the dialog. Call this after any externally controlled closing animation finishes. - `close`: Closes the dialog imperatively when called. |
| `children` | `ReactNode \| PayloadChildRenderFunction<unknown>` |  | The content of the dialog. This can be a regular React node or a render function that receives the `payload` of the active trigger. |
| `defaultOpen` | `boolean` | `false` | Whether the dialog is initially open. |
| `defaultTriggerId` | `string` |  | ID of the trigger that the dialog is associated with. This is useful in conjunction with the `defaultOpen` prop to create an initially open dialog. |
| `disablePointerDismissal` | `boolean` | `false` | Whether to prevent the dialog from closing on outside presses. For non-modal dialogs, this also prevents the dialog from closing when focus moves outside of it. |
| `handle` | `BaseDialog.Handle<unknown>` |  | A handle to associate the dialog with a trigger. If specified, allows external triggers to control the dialog's open state. Can be created with the Dialog.createHandle() method. |
| `modal` | `boolean \| "trap-focus"` | `true` | Determines if the dialog enters a modal state when open. - `true`: user interaction is limited to just the dialog: focus is trapped, document page scroll is locked, and pointer interactions on outside elements are disabled. - `false`: user interaction with the rest of the document is allowed. - `'trap-focus'`: focus is trapped inside the dialog, but document page scroll is not locked and pointer interactions outside of it remain enabled. |
| `onOpenChange` | `(open: boolean, eventDetails: BaseDialog.Root.ChangeEventDetails) => void` |  | Event handler called when the dialog is opened or closed. |
| `onOpenChangeComplete` | `(open: boolean) => void` |  | Event handler called after any animations complete when the dialog is opened or closed. |
| `open` | `boolean` |  | Whether the dialog is currently open. |
| `triggerId` | `string` |  | ID of the trigger that the dialog is associated with. This is useful in conjunction with the `open` prop to create a controlled dialog. There's no need to specify this prop when the dialog is uncontrolled (that is, when the `open` prop is not set). |

### AlertDialogAction

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `loading` | `boolean` |  |  |
| `loadingLabel` | `string` |  |  |
| `size` | `"md" \| "lg" \| "xl" \| "icon-md" \| "icon-lg" \| DeprecatedButtonSize` |  | `md` (32px) and `icon-md` for rows, cards, banners, toolbars and panel headers; `lg` and `icon-lg` (the control height) for dialog footers, forms and beside a field; `xl` for a full-width call to action. The size follows the place: see Button › Size by place. |
| `variant` | `"primary" \| "accent" \| "warning" \| "danger" \| "default" \| "outline" \| "information" \| "muted" \| "success" \| "danger-secondary" \| "danger-outline" \| "ghost" \| "on-frame"` |  |  |
| `focusableWhenDisabled` | `boolean` | `false` | Whether the button should be focusable when disabled. |
| `nativeButton` | `boolean` | `true` | Whether the component renders a native `<button>` element when replacing it via the `render` prop. Set to `false` if the rendered element is not a button (for example, `<div>`). |
| `render` | `ReactElement \| ((props, state) => ReactElement)` |  | Allows you to replace the component's HTML element with a different tag, or compose it with another component. |

Also takes the attributes of its element.

### AlertDialogBody

Also takes the attributes of its element.

### AlertDialogCancel

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `size` | `"md" \| "lg" \| "xl" \| "icon-md" \| "icon-lg" \| DeprecatedButtonSize` |  | `md` (32px) and `icon-md` for rows, cards, banners, toolbars and panel headers; `lg` and `icon-lg` (the control height) for dialog footers, forms and beside a field; `xl` for a full-width call to action. The size follows the place: see Button › Size by place. |
| `variant` | `"primary" \| "accent" \| "warning" \| "danger" \| "default" \| "outline" \| "information" \| "muted" \| "success" \| "danger-secondary" \| "danger-outline" \| "ghost" \| "on-frame"` |  |  |
| `nativeButton` | `boolean` | `true` | Whether the component renders a native `<button>` element when replacing it via the `render` prop. Set to `false` if the rendered element is not a button (for example, `<div>`). |

Also takes the attributes of its element.

### AlertDialogClose

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `children` | `ReactNode` |  |  |
| `size` | `"md" \| "lg" \| "xl" \| "icon-md" \| "icon-lg" \| DeprecatedButtonSize` |  | `md` (32px) and `icon-md` for rows, cards, banners, toolbars and panel headers; `lg` and `icon-lg` (the control height) for dialog footers, forms and beside a field; `xl` for a full-width call to action. The size follows the place: see Button › Size by place. |
| `variant` | `"primary" \| "accent" \| "warning" \| "danger" \| "default" \| "outline" \| "information" \| "muted" \| "success" \| "danger-secondary" \| "danger-outline" \| "ghost" \| "on-frame"` |  |  |
| `nativeButton` | `boolean` | `true` | Whether the component renders a native `<button>` element when replacing it via the `render` prop. Set to `false` if the rendered element is not a button (for example, `<div>`). |

Also takes the attributes of its element.

### AlertDialogContent

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `overlay` | `false \| AlertDialogOverlayProps` |  |  |
| `portalProps` | `AlertDialogPortalProps` |  |  |
| `finalFocus` | `boolean \| RefObject<HTMLElement \| null> \| ((closeType: InteractionType) => boolean \| HTMLElement \| null \| void)` |  | Determines the element to focus when the dialog is closed. |
| `initialFocus` | `boolean \| RefObject<HTMLElement \| null> \| ((openType: InteractionType) => boolean \| HTMLElement \| null \| void)` |  | Determines the element to focus when the dialog is opened. By default, focus moves to the first tabbable element inside the popup, except when the dialog is opened by touch — then the popup itself is focused to avoid opening the virtual keyboard. |
| `render` | `ReactElement \| ((props, state) => ReactElement)` |  | Allows you to replace the component's HTML element with a different tag, or compose it with another component. |

Also takes the attributes of its element.

### AlertDialogDescription

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `render` | `ReactElement \| ((props, state) => ReactElement)` |  | Allows you to replace the component's HTML element with a different tag, or compose it with another component. |

Also takes the attributes of its element.

### AlertDialogFooter

Also takes the attributes of its element.

### AlertDialogHeader

Also takes the attributes of its element.

### AlertDialogOverlay

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `forceRender` | `boolean` | `false` | Whether the backdrop is forced to render even when nested. |
| `render` | `ReactElement \| ((props, state) => ReactElement)` |  | Allows you to replace the component's HTML element with a different tag, or compose it with another component. |

Also takes the attributes of its element.

### AlertDialogPortal

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `container` | `HTMLElement \| ShadowRoot \| RefObject<HTMLElement \| ShadowRoot \| null>` |  | A parent element to render the portal element into. |
| `keepMounted` | `boolean` | `false` | Whether to keep the portal mounted in the DOM while the popup is hidden. |
| `render` | `ReactElement \| ((props, state) => ReactElement)` |  | Allows you to replace the component's HTML element with a different tag, or compose it with another component. |

Also takes the attributes of its element.

### AlertDialogTitle

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `render` | `ReactElement \| ((props, state) => ReactElement)` |  | Allows you to replace the component's HTML element with a different tag, or compose it with another component. |

Also takes the attributes of its element.

### AlertDialogTrigger

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `handle` | `BaseDialog.Handle<unknown>` |  | A handle to associate the trigger with a dialog. Can be created with the Dialog.createHandle() method. |
| `id` | `string` |  | ID of the trigger. In addition to being forwarded to the rendered element, it is also used to specify the active trigger for the dialog in controlled mode (with the DialogRoot `triggerId` prop). |
| `nativeButton` | `boolean` | `true` | Whether the component renders a native `<button>` element when replacing it via the `render` prop. Set to `false` if the rendered element is not a button (for example, `<div>`). |
| `payload` | `{}` |  | A payload to pass to the dialog when it is opened. |
| `render` | `ReactElement \| ((props, state) => ReactElement)` |  | Allows you to replace the component's HTML element with a different tag, or compose it with another component. |

Also takes the attributes of its element.

## Changes

- 0.8.3 (Fixed): A `Dialog` or `AlertDialog` opened from a sheet or another dialog draws its own, lighter scrim, so it no longer sits undimmed on the surface below. A sheet opened from a dialog does the same; a sheet over a sheet is unchanged. Nesting follows the modal roots, as in Base UI, and a `modal={false}` parent doesn't count.
