# AlertDialog

A modal confirmation dialog that interrupts the user with important content and expects an explicit response.

```slint
import { Button, ButtonVariant } from "@glint/components/button.slint";
import { AlertDialog } from "@glint/components/alert-dialog.slint";
import { Tokens } from "@glint/theme/tokens.slint";

export component Demo inherits Window {
    width: 560px;
    height: 320px;
    background: Tokens.color-background;

    VerticalLayout {
        alignment: center;
        padding: 24px;

        HorizontalLayout {
            alignment: center;

            Button {
                text: "Delete account";
                variant: ButtonVariant.destructive;
                haspopup: true;
                clicked => { alert.open = true; }
            }
        }
    }

    alert := AlertDialog {
        width: parent.width;
        height: parent.height;
        title: "Are you absolutely sure?";
        description: "This action cannot be undone. This will permanently delete your account and remove your data from our servers.";
        action-label: "Delete account";
        cancel-label: "Cancel";
    }
}
```

## Usage

```slint
import { AlertDialog } from "@glint/components/alert-dialog.slint";

export component AppWindow inherits Window {
    in-out property <bool> deleting: false;
    callback perform-delete();

    VerticalLayout {
        // your screen layout
    }

    // Last child of the window, sized to it: Slint has no portals, so what
    // draws on top is what comes last.
    AlertDialog {
        width: parent.width;
        height: parent.height;
        open <=> root.deleting;
        title: "Are you sure?";
        description: "This action cannot be undone.";
        action-label: "Delete";
        confirmed => { root.perform-delete(); }
    }
}
```

An `AlertDialog` is a focused confirmation modal that requires an explicit choice. Unlike `Dialog`, it provides no freeform body slot — its `description` is the entire message — and clicking the backdrop is intentionally a no-op so a stray click cannot dismiss an unanswered question.

Mount it **last** among the window’s children, sized to `width: parent.width; height: parent.height`.

## Examples

### Compact size

`size` offers two width presets: `default` (420px) for standard confirmation prompts and `sm` (320px) for brief questions that need little horizontal room.

```slint
import { Button, ButtonVariant } from "@glint/components/button.slint";
import { AlertDialog, AlertDialogSize } from "@glint/components/alert-dialog.slint";
import { Tokens } from "@glint/theme/tokens.slint";

export component Demo inherits Window {
    width: 560px;
    height: 320px;
    background: Tokens.color-background;

    VerticalLayout {
        alignment: center;
        padding: 24px;

        HorizontalLayout {
            alignment: center;

            Button {
                text: "Discard draft";
                variant: ButtonVariant.outline;
                haspopup: true;
                clicked => { alert.open = true; }
            }
        }
    }

    alert := AlertDialog {
        width: parent.width;
        height: parent.height;
        size: AlertDialogSize.sm;
        title: "Discard draft?";
        description: "Your changes will not be saved.";
        action-label: "Discard";
    }
}
```

### Action variant

`action-variant` styles the confirm button with any `ButtonVariant`. It defaults to `ButtonVariant.destructive` for destructive confirmations, and you set `ButtonVariant.default` or `ButtonVariant.outline` when asking for confirmation of a non-destructive action.

```slint
import { Button, ButtonVariant } from "@glint/components/button.slint";
import { AlertDialog } from "@glint/components/alert-dialog.slint";
import { Tokens } from "@glint/theme/tokens.slint";

export component Demo inherits Window {
    width: 560px;
    height: 320px;
    background: Tokens.color-background;

    VerticalLayout {
        alignment: center;
        padding: 24px;

        HorizontalLayout {
            alignment: center;

            Button {
                text: "Publish release";
                haspopup: true;
                clicked => { alert.open = true; }
            }
        }
    }

    alert := AlertDialog {
        width: parent.width;
        height: parent.height;
        title: "Publish release v2.0?";
        description: "This will make the new version available to all active subscribers.";
        action-label: "Publish";
        action-variant: ButtonVariant.default;
    }
}
```

### Handling confirmation and cancellation

`confirmed` fires when the action button is pressed; `cancelled` fires when the Cancel button is pressed or when the user presses `Escape`. The alert dialog closes itself on either path.

```slint
import { Button, ButtonVariant } from "@glint/components/button.slint";
import { AlertDialog } from "@glint/components/alert-dialog.slint";
import { Tokens } from "@glint/theme/tokens.slint";

export component Demo inherits Window {
    width: 560px;
    height: 320px;
    background: Tokens.color-background;

    in-out property <string> message: "Ready to archive";

    VerticalLayout {
        alignment: center;
        spacing: 12px;
        padding: 24px;

        HorizontalLayout {
            alignment: center;

            Button {
                text: "Archive project";
                variant: ButtonVariant.outline;
                haspopup: true;
                clicked => { alert.open = true; }
            }
        }

        Text {
            text: root.message;
            color: Tokens.color-muted-foreground;
            horizontal-alignment: center;
        }
    }

    alert := AlertDialog {
        width: parent.width;
        height: parent.height;
        title: "Archive this project?";
        description: "Archived projects become read-only for all team members.";
        action-label: "Archive";
        action-variant: ButtonVariant.default;
        confirmed => { root.message = "Project archived"; }
        cancelled => { root.message = "Archive cancelled"; }
    }
}
```

### Restoring focus

`restore-focus` fires on every close, so you can return keyboard focus to the button that triggered the alert dialog.

```slint
import { Button, ButtonVariant } from "@glint/components/button.slint";
import { AlertDialog } from "@glint/components/alert-dialog.slint";
import { Tokens } from "@glint/theme/tokens.slint";

export component Demo inherits Window {
    width: 560px;
    height: 320px;
    background: Tokens.color-background;

    VerticalLayout {
        alignment: center;
        padding: 24px;

        HorizontalLayout {
            alignment: center;

            trigger := Button {
                text: "Remove member";
                variant: ButtonVariant.destructive;
                haspopup: true;
                clicked => { alert.open = true; }
            }
        }
    }

    alert := AlertDialog {
        width: parent.width;
        height: parent.height;
        title: "Remove team member?";
        description: "They will lose access to all shared repositories.";
        action-label: "Remove";
        restore-focus => { trigger.focus(); }
    }
}
```

## API Reference

### Properties

| Property         | Type                 | Default                     | Description                                                     |
| ---------------- | -------------------- | --------------------------- | --------------------------------------------------------------- |
| `open`           | `in-out bool`        | `false`                     | Two-way; consumer sets true to show, Glint sets false on close. |
| `title`          | `in string`          | no default                  | Heading at the top of the modal.                                |
| `description`    | `in string`          | no default                  | Body text describing the consequences of the action.            |
| `action-label`   | `in string`          | `@tr("Continue")`           | Label for the destructive button (right side).                  |
| `cancel-label`   | `in string`          | `@tr("Cancel")`             | Label for the safe button (left side).                          |
| `action-variant` | `in ButtonVariant`   | `ButtonVariant.destructive` | Style for the action button — defaults to `destructive`.        |
| `size`           | `in AlertDialogSize` | `AlertDialogSize.default`   | Width preset — `default` or the compact `sm`.                   |

### Callbacks

| Callback          | Description                                                                                                                                                                                                                                                                                                           |
| ----------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `confirmed()`     | Fired when the action button is pressed; the modal closes itself.                                                                                                                                                                                                                                                     |
| `cancelled()`     | Fired on Cancel or Escape; the modal closes itself.                                                                                                                                                                                                                                                                   |
| `restore-focus()` | Fired on EVERY close, including one the consumer drives by setting `open = false`, so keyboard focus always gets a new home: `restore-focus => { my-button.focus(); }`. Slint exposes no "previously focused element", so only the trigger's owner can name it. Same contract `Dialog`, `Sheet` and `Drawer` publish. |

### Enums

| Enum              | Values                                                                             |
| ----------------- | ---------------------------------------------------------------------------------- |
| `ButtonVariant`   | `default`, `outline`, `secondary`, `ghost`, `link`, `destructive`, `glow`, `glass` |
| `AlertDialogSize` | `default`, `sm`                                                                    |

## Accessibility

- **Role and name.** Slint has no alertdialog role, so the open panel claims the closest landmark it has — a region — named by `title` and described by `description`. Assistive technology announces both upon presentation.
- **Initial focus.** Opening the alert dialog moves keyboard focus to the **Cancel** button by default, ensuring that an accidental `Enter` keypress never triggers a destructive action.
- **Keyboard navigation.** `Tab` and `Shift+Tab` cycle focus exclusively between the Cancel and Action buttons inside the modal card.
- **Keyboard dismissal.** `Escape` fires `cancelled()` and closes the alert dialog.
- **No backdrop dismissal.** Clicks on the dimmed scrim are ignored: unlike `Dialog`, an alert dialog requires the user to explicitly select one of the two choices.
- **Focus restoration.** `restore-focus` fires on every close so focus can be returned to the opening trigger.
- **The trigger.** The control that opens an alert dialog should set `haspopup: true`.
