# Alert Dialog

A modal dialog that asks the user to confirm an action.

Source: [alert-dialog.tsx](https://github.com/jakejarvis/jarvis-ui/blob/main/src/components/ui/alert-dialog.tsx)

```tsx
import * as React from "react";

import {
  AlertDialog,
  AlertDialogAction,
  AlertDialogCancel,
  AlertDialogContent,
  AlertDialogDescription,
  AlertDialogFooter,
  AlertDialogHeader,
  AlertDialogTitle,
  AlertDialogTrigger,
} from "@/components/ui/alert-dialog";
import { Button } from "@/components/ui/button";

export default function AlertDialogBasic() {
  const [open, setOpen] = React.useState(false);
  return (
    <AlertDialog open={open} onOpenChange={setOpen}>
      <AlertDialogTrigger render={<Button variant="secondary" />}>Sign out</AlertDialogTrigger>
      <AlertDialogContent>
        <AlertDialogHeader>
          <AlertDialogTitle>Sign out?</AlertDialogTitle>
          <AlertDialogDescription>
            You’ll need to sign in again on this device.
          </AlertDialogDescription>
        </AlertDialogHeader>
        <AlertDialogFooter>
          <AlertDialogCancel>Cancel</AlertDialogCancel>
          <AlertDialogAction onClick={() => setOpen(false)}>Sign out</AlertDialogAction>
        </AlertDialogFooter>
      </AlertDialogContent>
    </AlertDialog>
  );
}
```

## Installation

Add the registry, once per project:

```bash
npx shadcn@latest registry add @jarvis=https://ui.jarv.is/r/{name}.json
```

Then add the component:

```bash
npx shadcn@latest add @jarvis/alert-dialog
```

## Usage

```tsx
import * as React from "react";

import {
  AlertDialog,
  AlertDialogAction,
  AlertDialogCancel,
  AlertDialogContent,
  AlertDialogDescription,
  AlertDialogFooter,
  AlertDialogHeader,
  AlertDialogTitle,
  AlertDialogTrigger,
} from "@/components/ui/alert-dialog";
import { Button } from "@/components/ui/button";

export function LeaveTeam() {
  const [open, setOpen] = React.useState(false);
  return (
    <AlertDialog open={open} onOpenChange={setOpen}>
      <AlertDialogTrigger render={<Button variant="secondary" />}>Leave team</AlertDialogTrigger>
      <AlertDialogContent>
        <AlertDialogHeader>
          <AlertDialogTitle>Leave the team?</AlertDialogTitle>
          <AlertDialogDescription>You’ll lose access to its projects.</AlertDialogDescription>
        </AlertDialogHeader>
        <AlertDialogFooter>
          <AlertDialogCancel>Cancel</AlertDialogCancel>
          <AlertDialogAction onClick={() => setOpen(false)}>Leave</AlertDialogAction>
        </AlertDialogFooter>
      </AlertDialogContent>
    </AlertDialog>
  );
}
```

Unlike a [Dialog](https://ui.jarv.is/components/dialog.md), an alert dialog doesn't close when you click outside it.
`AlertDialogCancel` closes it, but `AlertDialogAction` doesn't, so control the dialog with `open`
and `onOpenChange` and close it when the action finishes.

Always include an `AlertDialogTitle` and `AlertDialogDescription`.

## Composition

- `AlertDialog`
  - `AlertDialogTrigger`
  - `AlertDialogContent`
    - `AlertDialogHeader`
      - `AlertDialogTitle`
      - `AlertDialogDescription`
    - `AlertDialogFooter`
      - `AlertDialogCancel`
      - `AlertDialogAction`

## Examples

### Destructive

Set `variant="destructive"` on the action for things that can't be undone.

```tsx
import { Trash2Icon } from "lucide-react";
import * as React from "react";

import {
  AlertDialog,
  AlertDialogAction,
  AlertDialogCancel,
  AlertDialogContent,
  AlertDialogDescription,
  AlertDialogFooter,
  AlertDialogHeader,
  AlertDialogTitle,
  AlertDialogTrigger,
} from "@/components/ui/alert-dialog";
import { Button } from "@/components/ui/button";
import { toast } from "@/components/ui/toast";

export default function AlertDialogDestructive() {
  const [open, setOpen] = React.useState(false);
  return (
    <AlertDialog open={open} onOpenChange={setOpen}>
      <AlertDialogTrigger render={<Button variant="destructive" />}>
        <Trash2Icon />
        Delete project
      </AlertDialogTrigger>
      <AlertDialogContent>
        <AlertDialogHeader>
          <AlertDialogTitle>Delete “Website redesign”?</AlertDialogTitle>
          <AlertDialogDescription>
            This permanently deletes the project and its 28 tasks. Anyone with the link will see a
            “not found” page. This can’t be undone.
          </AlertDialogDescription>
        </AlertDialogHeader>
        <AlertDialogFooter>
          <AlertDialogCancel>Cancel</AlertDialogCancel>
          <AlertDialogAction
            variant="destructive"
            onClick={() => {
              setOpen(false);
              toast.add({ title: "Project deleted" });
            }}
          >
            Delete
          </AlertDialogAction>
        </AlertDialogFooter>
      </AlertDialogContent>
    </AlertDialog>
  );
}
```

## Props

| Part | Extends |
| --- | --- |
| `AlertDialog` | [`AlertDialog.Root`](https://base-ui.com/react/components/alert-dialog#root) |
| `AlertDialogTrigger` | [`AlertDialog.Trigger`](https://base-ui.com/react/components/alert-dialog#trigger) |
| `AlertDialogPortal` | [`AlertDialog.Portal`](https://base-ui.com/react/components/alert-dialog#portal) |
| `AlertDialogOverlay` | [`AlertDialog.Backdrop`](https://base-ui.com/react/components/alert-dialog#backdrop) |
| `AlertDialogContent` | [`AlertDialog.Popup`](https://base-ui.com/react/components/alert-dialog#popup) |
| `AlertDialogHeader` | `<div>` |
| `AlertDialogFooter` | `<div>` |
| `AlertDialogTitle` | [`AlertDialog.Title`](https://base-ui.com/react/components/alert-dialog#title) |
| `AlertDialogDescription` | [`AlertDialog.Description`](https://base-ui.com/react/components/alert-dialog#description) |
| `AlertDialogAction` | [`Button`](https://ui.jarv.is/components/button.md) |
| `AlertDialogCancel` | [`AlertDialog.Close`](https://base-ui.com/react/components/alert-dialog#close) |

The tables leave out `className`, `style` and `render`. Parts built on Base UI take them as its [styling](https://base-ui.com/react/handbook/styling) and [composition](https://base-ui.com/react/handbook/composition) guides describe.

### AlertDialog

| Prop                    | Type                                                                           | Description                                                                                                                                                                                                                                                                                                                                                                                        |
| ----------------------- | ------------------------------------------------------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `onOpenChange?`         | `((open: boolean, eventDetails: AlertDialog.Root.ChangeEventDetails) => void)` | Event handler called when the alert dialog is opened or closed.                                                                                                                                                                                                                                                                                                                                    |
| `actionsRef?`           | `React.RefObject<DialogRootActions \| null>`                                   | A ref to imperative actions. - `unmount`: Ends the closing phase of the alert dialog after an externally controlled closing animation finishes. Call `preventUnmountOnClose()` in `onOpenChange` first, otherwise the alert dialog completes closing on its own. Whether it leaves the DOM is decided by `keepMounted` on the portal. - `close`: Closes the alert dialog imperatively when called. |
| `handle?`               | `AlertDialog.Handle<unknown>`                                                  | 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.                                                                                                                                                                                                 |
| `open?`                 | `boolean`                                                                      | Whether the dialog is currently open.                                                                                                                                                                                                                                                                                                                                                              |
| `defaultOpen?`          | `boolean`                                                                      | Whether the dialog is initially open. To render a controlled dialog, use the `open` prop instead. Default: `false`                                                                                                                                                                                                                                                                                 |
| `onOpenChangeComplete?` | `((open: boolean) => void)`                                                    | Event handler called after any animations complete when the dialog is opened or closed.                                                                                                                                                                                                                                                                                                            |
| `children?`             | `PayloadChildRenderFunction<unknown> \| React.ReactNode`                       | The content of the dialog. This can be a regular React node or a render function that receives the `payload` of the active trigger.                                                                                                                                                                                                                                                                |
| `triggerId?`            | `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).                                                                                                                                           |
| `defaultTriggerId?`     | `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.                                                                                                                                                                                                                                                |

### AlertDialogTrigger

| Prop            | Type                          | Description                                                                                                                                                                                        |
| --------------- | ----------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `handle?`       | `AlertDialog.Handle<unknown>` | A handle to associate the trigger with an alert dialog. Can be created with the AlertDialog.createHandle() method.                                                                                 |
| `nativeButton?` | `boolean`                     | 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>`). Default: `true`  |
| `payload?`      | `unknown`                     | A payload to pass to the dialog when it is opened.                                                                                                                                                 |
| `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). |

### AlertDialogPortal

| Prop           | Type                                                                                      | Description                                                                               |
| -------------- | ----------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------- |
| `keepMounted?` | `boolean`                                                                                 | Whether to keep the portal mounted in the DOM while the popup is hidden. Default: `false` |
| `container?`   | `HTMLElement \| React.RefObject<HTMLElement \| ShadowRoot \| null> \| ShadowRoot \| null` | A parent element to render the portal element into.                                       |

### AlertDialogOverlay

| Prop           | Type      | Description                                                                 |
| -------------- | --------- | --------------------------------------------------------------------------- |
| `forceRender?` | `boolean` | Whether the backdrop is forced to render even when nested. Default: `false` |

### AlertDialogContent

| Prop            | Type                                                                                                                          | Description                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          |
| --------------- | ----------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `initialFocus?` | `boolean \| React.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. - `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. |
| `finalFocus?`   | `boolean \| React.RefObject<HTMLElement \| null> \| ((closeType: InteractionType) => boolean \| HTMLElement \| null \| void)` | 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.                                                                                                                                                                                       |

### AlertDialogAction

| Prop                     | Type                                                                                 | Description                                                                                                                                                                                       |
| ------------------------ | ------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `focusableWhenDisabled?` | `boolean`                                                                            | Whether the button should be focusable when disabled. Default: `false`                                                                                                                            |
| `nativeButton?`          | `boolean`                                                                            | 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>`). Default: `true` |
| `variant?`               | `"destructive" \| "ghost" \| "link" \| "outline" \| "primary" \| "secondary"`        | Default: `"primary"`                                                                                                                                                                              |
| `size?`                  | `"default" \| "icon" \| "icon-lg" \| "icon-sm" \| "icon-xs" \| "lg" \| "sm" \| "xs"` | Default: `"default"`                                                                                                                                                                              |

### AlertDialogCancel

| Prop            | Type                                                                                 | Description                                                                                                                                                                                       |
| --------------- | ------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `nativeButton?` | `boolean`                                                                            | 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>`). Default: `true` |
| `variant?`      | `"destructive" \| "ghost" \| "link" \| "outline" \| "primary" \| "secondary"`        | Default: `"secondary"`                                                                                                                                                                            |
| `size?`         | `"default" \| "icon" \| "icon-lg" \| "icon-sm" \| "icon-xs" \| "lg" \| "sm" \| "xs"` | Default: `"default"`                                                                                                                                                                              |
