> ## Documentation Index
> Fetch the complete documentation index at: https://docs.twenty.com/llms.txt
> Use this file to discover all available pages before exploring further.

# AlertDialog

> Ask for confirmation before an action that needs an explicit decision.

export const StoryEmbed = ({storyId, title, height = 240}) => <>
    <Tabs>
      <Tab title="Light">
        <iframe title={`${title} (light)`} src={`https://storybook.twenty.com/iframe.html?id=${storyId}&viewMode=story&globals=colorScheme:light`} width="100%" height={height} loading="lazy" style={{
  border: 0
}} />
      </Tab>
      <Tab title="Dark">
        <iframe title={`${title} (dark)`} src={`https://storybook.twenty.com/iframe.html?id=${storyId}&viewMode=story&globals=colorScheme:dark`} width="100%" height={height} loading="lazy" style={{
  border: 0
}} />
      </Tab>
    </Tabs>
    <a href={`https://storybook.twenty.com/?path=/story/${storyId}`}>
      Open in Storybook
    </a>
  </>;

Use `AlertDialog` for a decision that interrupts the current workflow, such as confirming deletion. It provides an accessible modal with a backdrop and focus management.

<StoryEmbed storyId="ui-surfaces-alertdialog--documentation" title="AlertDialog example" height={440} />

## Anatomy

Keep the trigger and popup inside `AlertDialog.Root`. This tree shows the recommended layout for a confirmation dialog.

```text theme={null}
AlertDialog.Root
├── AlertDialog.Trigger
└── AlertDialog.Popup
    ├── AlertDialog.Header
    │   ├── AlertDialog.Title
    │   └── AlertDialog.Description
    ├── AlertDialog.Body
    └── AlertDialog.Footer
        ├── AlertDialog.Close
        └── Confirmation action
```

| Part                       | Requirement                                   | Purpose                                                                  |
| -------------------------- | --------------------------------------------- | ------------------------------------------------------------------------ |
| `Root`                     | Required                                      | Coordinates open state and modal behavior.                               |
| `Trigger`                  | Optional for a programmatically opened dialog | Opens the dialog and provides a return focus target.                     |
| `Popup`                    | Required                                      | Renders the modal content with focus management.                         |
| `Title`                    | Recommended                                   | Supplies the visible dialog name. An accessible name is always required. |
| `Description`              | Recommended for a confirmation                | Explains the decision and its consequences.                              |
| `Header`, `Body`, `Footer` | Optional layout parts                         | Arrange headings, additional content, and actions.                       |
| `Close`                    | Recommended for cancellation                  | Supplies an explicit close action.                                       |

`Popup` includes the portal, backdrop, and viewport. Put content directly inside it and set `size`, `container`, and focus props on `Popup`. `Header`, `Body`, and `Footer` arrange content; `Title` and `Description` provide the accessible relationships.

The confirmation action is application content, not an exported part. Use `Close` with a synchronous handler or a `Button` with controlled open state for asynchronous confirmation.

## Uncontrolled state

Use `defaultOpen` to set the initial visibility. The dialog owns subsequent changes from its trigger, close controls, and dismissal interactions.

```tsx theme={null}
import { AlertDialog } from 'twenty-ui/primitives/surfaces';

type DeleteConfirmationProps = { onDelete: () => void };

export const DeleteConfirmation = ({ onDelete }: DeleteConfirmationProps) => (
  <AlertDialog.Root defaultOpen={false}>
    <AlertDialog.Trigger>Delete record</AlertDialog.Trigger>
    <AlertDialog.Popup>
      <AlertDialog.Header>
        <AlertDialog.Title>Delete this record?</AlertDialog.Title>
        <AlertDialog.Description>
          This action cannot be undone.
        </AlertDialog.Description>
      </AlertDialog.Header>
      <AlertDialog.Footer>
        <AlertDialog.Close>Cancel</AlertDialog.Close>
        <AlertDialog.Close onClick={onDelete}>Delete</AlertDialog.Close>
      </AlertDialog.Footer>
    </AlertDialog.Popup>
  </AlertDialog.Root>
);
```

`defaultOpen` defaults to `false`, so it can be omitted. This example uses a synchronous confirmation callback and closes after the action runs.

## Controlled state

Pass `open` and update it with `onOpenChange` to own the same dialog's visibility in React state. The callback receives the next boolean and event details, including changes requested by the trigger and close controls.

```tsx theme={null}
import { useState } from 'react';
import { AlertDialog } from 'twenty-ui/primitives/surfaces';

type DeleteConfirmationProps = { onDelete: () => void };

export const DeleteConfirmation = ({ onDelete }: DeleteConfirmationProps) => {
  const [open, setOpen] = useState(false);

  return (
    <AlertDialog.Root open={open} onOpenChange={setOpen}>
      <AlertDialog.Trigger>Delete record</AlertDialog.Trigger>
      <AlertDialog.Popup>
        <AlertDialog.Header>
          <AlertDialog.Title>Delete this record?</AlertDialog.Title>
          <AlertDialog.Description>
            This action cannot be undone.
          </AlertDialog.Description>
        </AlertDialog.Header>
        <AlertDialog.Footer>
          <AlertDialog.Close>Cancel</AlertDialog.Close>
          <AlertDialog.Close onClick={onDelete}>Delete</AlertDialog.Close>
        </AlertDialog.Footer>
      </AlertDialog.Popup>
    </AlertDialog.Root>
  );
};
```

For asynchronous confirmation, use a `Button` with your action handler instead of `AlertDialog.Close`. Keep `open` true while the action is pending, call `setOpen(false)` after it succeeds, and show an error inside the dialog if it fails.

## Compose with buttons

Use `render` to give the trigger and close controls Twenty UI button styling. The dialog parts supply their interaction handlers and refs to the buttons.

```tsx theme={null}
import { Button } from 'twenty-ui/primitives/input';
import { AlertDialog } from 'twenty-ui/primitives/surfaces';

type DeleteConfirmationProps = { onDelete: () => void };

export const DeleteConfirmation = ({ onDelete }: DeleteConfirmationProps) => (
  <AlertDialog.Root>
    <AlertDialog.Trigger
      render={<Button title="Delete record" accent="danger" />}
    />
    <AlertDialog.Popup>
      <AlertDialog.Header>
        <AlertDialog.Title>Delete this record?</AlertDialog.Title>
        <AlertDialog.Description>
          This action cannot be undone.
        </AlertDialog.Description>
      </AlertDialog.Header>
      <AlertDialog.Footer>
        <AlertDialog.Close
          render={<Button title="Cancel" variant="secondary" />}
        />
        <AlertDialog.Close
          onClick={onDelete}
          render={<Button title="Delete" accent="danger" />}
        />
      </AlertDialog.Footer>
    </AlertDialog.Popup>
  </AlertDialog.Root>
);
```

Keep each action as a single interactive control. If you wrap `Button` in your own component, [forward the supplied props and ref](/ui/primitives/overview#custom-components).

## Sizing and portals

`Popup.size` defaults to `md`; see the reference for supported sizes. Use `container` to override the theme's portal container and `keepMounted` to retain mounted content when closed.

## Focus and dismissal

The dialog traps focus while open. Escape can dismiss it; clicking the backdrop does not. Always provide a visible Cancel or Close action. Keep the initial focus on the least destructive action, and preserve a meaningful return focus target when the action removes its trigger. Use `Popup.initialFocus` and `Popup.finalFocus` to customize focus behavior.

## Props

The reference is generated from the public component types. Native attributes, including accessible names and event handlers, are also accepted on parts that render elements.

### AlertDialog.Root

<ParamField body="Root.actionsRef" type="RefObject<DialogRootActions | null>">
  A ref to imperative actions.

  * `unmount`: Manually unmounts the alert dialog.
    Call this after any externally controlled closing animation finishes.
  * `close`: Closes the alert dialog imperatively when called.
</ParamField>

<ParamField body="Root.children" type="ReactNode | PayloadChildRenderFunction<Payload>">
  The content of the dialog.
  This can be a regular React node or a render function that receives the `payload` of the active trigger.
</ParamField>

<ParamField body="Root.defaultOpen" type="boolean" default="false">
  Whether the dialog is initially open.

  To render a controlled dialog, use the `open` prop instead.
</ParamField>

<ParamField body="Root.defaultTriggerId" type="string | null">
  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.
</ParamField>

<ParamField body="Root.handle" type="AlertDialogHandle<Payload>">
  A handle to associate the alert dialog with a trigger.
  If specified, allows external triggers to control the alert dialog's open state.
  Can be created with the AlertDialog.createHandle() method.
</ParamField>

<ParamField body="Root.onOpenChange" type="((open: boolean, eventDetails: AlertDialogRootChangeEventDetails) => void)">
  Event handler called when the alert dialog is opened or closed.
</ParamField>

<ParamField body="Root.onOpenChangeComplete" type="((open: boolean) => void)">
  Event handler called after any animations complete when the dialog is opened or closed.
</ParamField>

<ParamField body="Root.open" type="boolean">
  Whether the dialog is currently open.
</ParamField>

<ParamField body="Root.triggerId" type="string | null">
  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).
</ParamField>

### AlertDialog.Trigger

<ParamField body="Trigger.className" type="string | ((state: DialogTriggerState) => string | undefined)">
  CSS class applied to the element, or a function that
  returns a class based on the component's state.
</ParamField>

<ParamField body="Trigger.handle" type="AlertDialogHandle<Payload>">
  A handle to associate the trigger with an alert dialog.
  Can be created with the AlertDialog.createHandle() method.
</ParamField>

<ParamField body="Trigger.id" type="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).
</ParamField>

<ParamField body="Trigger.nativeButton" type="boolean" default="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>`).
</ParamField>

<ParamField body="Trigger.payload" type="Payload">
  A payload to pass to the dialog when it is opened.
</ParamField>

<ParamField body="Trigger.render" type="ReactElement<unknown, string | JSXElementConstructor<any>> | ComponentRenderFn<HTMLProps, DialogTriggerState>">
  Allows you to replace the component's HTML element
  with a different tag, or compose it with another component.

  Accepts a `ReactElement` or a function that returns the element to render.
</ParamField>

<ParamField body="Trigger.style" type="CSSProperties | ((state: DialogTriggerState) => CSSProperties | undefined)">
  Style applied to the element, or a function that
  returns a style object based on the component's state.
</ParamField>

### AlertDialog.Popup

<ParamField body="Popup.className" type="string | ((state: DialogPopupState) => string | undefined)">
  CSS class applied to the element, or a function that
  returns a class based on the component's state.
</ParamField>

<ParamField body="Popup.container" type="HTMLElement | ShadowRoot | RefObject<HTMLElement | ShadowRoot | null> | null">
  Element the dialog is portaled into. Defaults to the theme's portal
  container.
</ParamField>

<ParamField body="Popup.finalFocus" type="boolean | RefObject<HTMLElement | null> | ((closeType: InteractionType) => boolean | void | HTMLElement | null)">
  Determines the element to focus when the dialog is closed.

  * `false`: Do not move focus.
  * `true`: Move focus based on the default behavior (trigger or previously focused element).
  * `RefObject`: Move focus to the ref element.
  * `function`: Called with the interaction type (`mouse`, `touch`, `pen`, or `keyboard`).
    Return an element to focus, `true` to use the default behavior, `null` to fall back to the default behavior, or `false`/`undefined` to do nothing.
</ParamField>

<ParamField body="Popup.initialFocus" type="boolean | RefObject<HTMLElement | null> | ((openType: InteractionType) => boolean | void | HTMLElement | null)">
  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.

  * `false`: Do not move focus.
  * `true`: Move focus based on the default behavior (first tabbable element or popup).
  * `RefObject`: Move focus to the ref element.
  * `function`: Called with the interaction type (`mouse`, `touch`, `pen`, or `keyboard`).
    Return an element to focus, `true` to use the default behavior, `null` to fall back to the default behavior, or `false`/`undefined` to do nothing.
</ParamField>

<ParamField body="Popup.keepMounted" type="boolean">
  Keeps the dialog mounted in the DOM while it is closed.
</ParamField>

<ParamField body="Popup.render" type="ReactElement<unknown, string | JSXElementConstructor<any>> | ComponentRenderFn<HTMLProps, DialogPopupState>">
  Allows you to replace the component's HTML element
  with a different tag, or compose it with another component.

  Accepts a `ReactElement` or a function that returns the element to render.
</ParamField>

<ParamField body="Popup.size" type="&#x22;sm&#x22; | &#x22;md&#x22; | &#x22;lg&#x22; | &#x22;xl&#x22; | &#x22;fullscreen&#x22;" default="md">
  Width of the dialog, or `fullscreen` to fill the viewport.
</ParamField>

<ParamField body="Popup.style" type="CSSProperties | ((state: DialogPopupState) => CSSProperties | undefined)">
  Style applied to the element, or a function that
  returns a style object based on the component's state.
</ParamField>

### AlertDialog.Title

<ParamField body="Title.className" type="string | ((state: DialogTitleState) => string | undefined)">
  CSS class applied to the element, or a function that
  returns a class based on the component's state.
</ParamField>

<ParamField body="Title.render" type="ReactElement<unknown, string | JSXElementConstructor<any>> | ComponentRenderFn<HTMLProps, DialogTitleState>">
  Allows you to replace the component's HTML element
  with a different tag, or compose it with another component.

  Accepts a `ReactElement` or a function that returns the element to render.
</ParamField>

<ParamField body="Title.style" type="CSSProperties | ((state: DialogTitleState) => CSSProperties | undefined)">
  Style applied to the element, or a function that
  returns a style object based on the component's state.
</ParamField>

### AlertDialog.Description

<ParamField body="Description.className" type="string | ((state: DialogDescriptionState) => string | undefined)">
  CSS class applied to the element, or a function that
  returns a class based on the component's state.
</ParamField>

<ParamField body="Description.render" type="ReactElement<unknown, string | JSXElementConstructor<any>> | ComponentRenderFn<HTMLProps, DialogDescriptionState>">
  Allows you to replace the component's HTML element
  with a different tag, or compose it with another component.

  Accepts a `ReactElement` or a function that returns the element to render.
</ParamField>

<ParamField body="Description.style" type="CSSProperties | ((state: DialogDescriptionState) => CSSProperties | undefined)">
  Style applied to the element, or a function that
  returns a style object based on the component's state.
</ParamField>

### AlertDialog.Close

<ParamField body="Close.className" type="string | ((state: DialogCloseState) => string | undefined)">
  CSS class applied to the element, or a function that
  returns a class based on the component's state.
</ParamField>

<ParamField body="Close.nativeButton" type="boolean" default="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>`).
</ParamField>

<ParamField body="Close.render" type="ReactElement<unknown, string | JSXElementConstructor<any>> | ComponentRenderFn<HTMLProps, DialogCloseState>">
  Allows you to replace the component's HTML element
  with a different tag, or compose it with another component.

  Accepts a `ReactElement` or a function that returns the element to render.
</ParamField>

<ParamField body="Close.style" type="CSSProperties | ((state: DialogCloseState) => CSSProperties | undefined)">
  Style applied to the element, or a function that
  returns a style object based on the component's state.
</ParamField>

### AlertDialog.Header

<ParamField body="Header.render" type="ReactElement<unknown, string | JSXElementConstructor<any>> | ComponentRenderFn<HTMLProps, {}>">
  Allows you to replace the component's HTML element
  with a different tag, or compose it with another component.

  Accepts a `ReactElement` or a function that returns the element to render.
</ParamField>

### AlertDialog.Body

<ParamField body="Body.render" type="ReactElement<unknown, string | JSXElementConstructor<any>> | ComponentRenderFn<HTMLProps, {}>">
  Allows you to replace the component's HTML element
  with a different tag, or compose it with another component.

  Accepts a `ReactElement` or a function that returns the element to render.
</ParamField>

### AlertDialog.Footer

<ParamField body="Footer.render" type="ReactElement<unknown, string | JSXElementConstructor<any>> | ComponentRenderFn<HTMLProps, {}>">
  Allows you to replace the component's HTML element
  with a different tag, or compose it with another component.

  Accepts a `ReactElement` or a function that returns the element to render.
</ParamField>
