# Alert Dialog

Confirmation dialog with role="alertdialog". Outside clicks never dismiss it, focus starts on Close, and Close and Confirm replace the corner close button.

- Package: `@mielui/svelte`
- Component version: `1.2.0`
- Depends on Mielui components: _internal/utils, dialog, button, typography
- Shared utilities: utils.cn

## Install

~~~~sh
pnpm dlx @mielui/svelte add alert-dialog
~~~~

## API

This reference is generated at build time from the component manifest, public `index.ts`, and documentation examples below. Changes to those source files are reflected here in the published Markdown. Standard Svelte and HTML attributes accepted by the exported prop types are supported.


### Close

| Prop | Type | Default | Required | Bindable | Description |
| --- | --- | --- | --- | --- | --- |
| closeOnClick | boolean \| undefined | true | No | No | Closes the dialog after the button is clicked. Set false to keep it open while work finishes. |
| disabled | boolean \| undefined | - | No | No | Prevents activation. A disabled link loses its destination and is skipped by Tab. |
| variant | ButtonVariant \| undefined | - | No | No | Visual style. Choose it for what the action means, not for decoration. |
| size | "sm" \| "md" \| "lg" \| "icon" \| undefined | - | No | No | Control height. `icon` is a square button for a single icon. |
| children | Snippet<[]> \| undefined | - | No | No | Content rendered inside. |
| element | HTMLButtonElement \| HTMLAnchorElement \| undefined | - | No | Yes | Bindable reference to the rendered DOM element. Type is the union of the two possible element types -- narrow at the use site: |
| unstyled | boolean \| undefined | - | No | No | Skip the variant/size base classes and render with `class` alone. |
| status | ButtonStatus \| undefined | - | No | No | Controlled visual state. Loading remains focusable and refuses activation. |
| loading | boolean \| undefined | - | No | No | Convenience alias for `status="loading"`. |
| labels | ButtonLabels \| undefined | - | No | No | Overrides the built-in text and accessible names. Every key is optional and English is the fallback. |
| onclick | ((event: MouseEvent) => void) \| undefined | - | No | No | Called when the button is activated. Loading and disabled buttons do not call it. |
| onkeydown | ((event: KeyboardEvent) => void) \| undefined | - | No | No | Called on key down, before the button handles the key itself. |
| href | string \| undefined | - | No | No | Renders a link to this address instead of a button. |

Also accepts the native HTML attributes and events listed in the rendered API reference.

### Confirm

| Prop | Type | Default | Required | Bindable | Description |
| --- | --- | --- | --- | --- | --- |
| closeOnClick | boolean \| undefined | true | No | No | Closes the dialog after the button is clicked. Set false to keep it open while work finishes. |
| disabled | boolean \| undefined | - | No | No | Prevents activation. A disabled link loses its destination and is skipped by Tab. |
| variant | ButtonVariant \| undefined | - | No | No | Visual style. Choose it for what the action means, not for decoration. |
| size | "sm" \| "md" \| "lg" \| "icon" \| undefined | - | No | No | Control height. `icon` is a square button for a single icon. |
| children | Snippet<[]> \| undefined | - | No | No | Content rendered inside. |
| element | HTMLButtonElement \| HTMLAnchorElement \| undefined | - | No | Yes | Bindable reference to the rendered DOM element. Type is the union of the two possible element types -- narrow at the use site: |
| unstyled | boolean \| undefined | - | No | No | Skip the variant/size base classes and render with `class` alone. |
| status | ButtonStatus \| undefined | - | No | No | Controlled visual state. Loading remains focusable and refuses activation. |
| loading | boolean \| undefined | - | No | No | Convenience alias for `status="loading"`. |
| labels | ButtonLabels \| undefined | - | No | No | Overrides the built-in text and accessible names. Every key is optional and English is the fallback. |
| onclick | ((event: MouseEvent) => void) \| undefined | - | No | No | Called when the button is activated. Loading and disabled buttons do not call it. |
| onkeydown | ((event: KeyboardEvent) => void) \| undefined | - | No | No | Called on key down, before the button handles the key itself. |
| href | string \| undefined | - | No | No | Renders a link to this address instead of a button. |

Also accepts the native HTML attributes and events listed in the rendered API reference.

### Content

| Prop | Type | Default | Required | Bindable | Description |
| --- | --- | --- | --- | --- | --- |
| surface | "solid" \| "glass" \| undefined | - | No | No | Surface treatment. Omit it to inherit `--mielui-surface` from the theme. |
| ariaBusy | boolean \| undefined | - | No | No | Marks the dialog busy for assistive technology while an action runs. |
| allowEscape | boolean \| undefined | true | No | No | Lets Escape dismiss the dialog. |
| size | DialogSize \| undefined | 'xs' | No | No | Maximum width of the panel. Defaults to `xs`. |
| class | string \| undefined | - | No | No | Classes added to the element. |
| children | Snippet<[]> \| undefined | - | No | No | Content rendered inside. |



### Description

| Prop | Type | Default | Required | Bindable | Description |
| --- | --- | --- | --- | --- | --- |
| class | string \| undefined | - | No | No | Classes added to the element. |
| children | Snippet<[]> \| undefined | - | No | No | Content rendered inside. |



### Footer

| Prop | Type | Default | Required | Bindable | Description |
| --- | --- | --- | --- | --- | --- |
| class | string \| undefined | - | No | No | Classes added to the element. |
| children | Snippet<[]> \| undefined | - | No | No | Content rendered inside. |



### Header

| Prop | Type | Default | Required | Bindable | Description |
| --- | --- | --- | --- | --- | --- |
| class | string \| undefined | - | No | No | Classes added to the element. |
| children | Snippet<[]> \| undefined | - | No | No | Content rendered inside. |



### Root

| Prop | Type | Default | Required | Bindable | Description |
| --- | --- | --- | --- | --- | --- |
| open | boolean \| undefined | false | No | Yes | Whether it is open. Bind it to control the state from outside. |
| onOpenChange | ((open: boolean) => void) \| undefined | - | No | No | Called with the new state whenever it opens or closes. |
| error | boolean \| undefined | false | No | No | Sets supported browser chrome to red while the alert dialog is open. |
| children | Snippet<[]> \| undefined | - | No | No | Content rendered inside. |



### Title

| Prop | Type | Default | Required | Bindable | Description |
| --- | --- | --- | --- | --- | --- |
| class | string \| undefined | - | No | No | Classes added to the element. |
| children | Snippet<[]> \| undefined | - | No | No | Content rendered inside. |



### Trigger

| Prop | Type | Default | Required | Bindable | Description |
| --- | --- | --- | --- | --- | --- |
| disabled | boolean \| undefined | - | No | No | Prevents activation. A disabled link loses its destination and is skipped by Tab. |
| variant | ButtonVariant \| undefined | - | No | No | Visual style. Choose it for what the action means, not for decoration. |
| size | "sm" \| "md" \| "lg" \| "icon" \| undefined | - | No | No | Control height. `icon` is a square button for a single icon. |
| children | Snippet<[]> \| undefined | - | No | No | Content rendered inside. |
| element | HTMLButtonElement \| HTMLAnchorElement \| undefined | - | No | Yes | Bindable reference to the rendered DOM element. Type is the union of the two possible element types -- narrow at the use site: |
| unstyled | boolean \| undefined | - | No | No | Skip the variant/size base classes and render with `class` alone. |
| status | ButtonStatus \| undefined | - | No | No | Controlled visual state. Loading remains focusable and refuses activation. |
| loading | boolean \| undefined | - | No | No | Convenience alias for `status="loading"`. |
| labels | ButtonLabels \| undefined | - | No | No | Overrides the built-in text and accessible names. Every key is optional and English is the fallback. |
| onclick | ((event: MouseEvent) => void) \| undefined | - | No | No | Called when the button is activated. Loading and disabled buttons do not call it. |
| onkeydown | ((event: KeyboardEvent) => void) \| undefined | - | No | No | Called on key down, before the button handles the key itself. |
| href | string \| undefined | - | No | No | Renders a link to this address instead of a button. |

Also accepts the native HTML attributes and events listed in the rendered API reference.

### Public types

~~~~ts
import type { ButtonProps } from '@mielui/svelte/components/button';
import type { DialogSize } from '@mielui/svelte/components/dialog';
import type { DefaultProps } from '@mielui/svelte/utils';
import type { Snippet } from 'svelte';
import Root from './alert-dialog.svelte';
import Close from './alert-dialog-close.svelte';
import Confirm from './alert-dialog-confirm.svelte';
import Content from './alert-dialog-content.svelte';
import Description from './alert-dialog-description.svelte';
import Footer from './alert-dialog-footer.svelte';
import Header from './alert-dialog-header.svelte';
import Title from './alert-dialog-title.svelte';
import Trigger from './alert-dialog-trigger.svelte';

export type AlertDialogProps = {
    /** Whether it is open. Bind it to control the state from outside. */
    open?: boolean;
    /** Called with the new state whenever it opens or closes. */
    onOpenChange?: (open: boolean) => void;
    /** Sets supported browser chrome to red while the alert dialog is open. */
    error?: boolean;
    /** Content rendered inside. */
    children?: Snippet;
};

export type AlertDialogContentProps = {
    /** Surface treatment. Omit it to inherit `--mielui-surface` from the theme. */
    surface?: 'solid' | 'glass';
    /** Marks the dialog busy for assistive technology while an action runs. */
    ariaBusy?: boolean;
    /** Lets Escape dismiss the dialog. */
    allowEscape?: boolean;
    /** Maximum width of the panel. Defaults to `xs`. */
    size?: DialogSize;
} & DefaultProps;

export type AlertDialogActionProps = {
    /**
     * Closes the dialog after the button is clicked. Set false to keep it open while work finishes.
     */
    closeOnClick?: boolean;
} & ButtonProps;

export { Close, Confirm, Content, Description, Footer, Header, Root, Title, Trigger };
~~~~

## Examples

### Async Delete

~~~~svelte
<script lang="ts">
    import * as AlertDialog from '@mielui/svelte/components/alert-dialog';

    let open = $state(false);
    let deleting = $state(false);
    let log = $state('Nothing deleted yet');

    function remove(event: MouseEvent) {
        event.preventDefault();
        deleting = true;
        setTimeout(() => {
            deleting = false;
            open = false;
            log = 'Branch deleted';
        }, 1200);
    }
</script>

<div class="flex flex-col items-center gap-3">
    <AlertDialog.Root
        bind:open
        error
        onOpenChange={(next) => {
            if (next) {
                log = 'Waiting for an answer';
            }
        }}
    >
        <AlertDialog.Trigger variant="outline">Delete branch</AlertDialog.Trigger>
        <AlertDialog.Content allowEscape={false}>
            <AlertDialog.Header>
                <AlertDialog.Title>Delete feat/rate-limit?</AlertDialog.Title>
                <AlertDialog.Description>
                    Escape is off here, so the only ways out are the two buttons.
                </AlertDialog.Description>
            </AlertDialog.Header>
            <AlertDialog.Footer>
                <AlertDialog.Close disabled={deleting}>Keep it</AlertDialog.Close>
                <AlertDialog.Confirm
                    loading={deleting}
                    labels={{ loading: 'Deleting' }}
                    onclick={remove}
                >
                    Delete branch
                </AlertDialog.Confirm>
            </AlertDialog.Footer>
        </AlertDialog.Content>
    </AlertDialog.Root>
    <p class="text-sm text-foreground-muted">{log}</p>
</div>
~~~~

### Destructive

~~~~svelte
<script lang="ts">
    import * as AlertDialog from '@mielui/svelte/components/alert-dialog';
    import Kbd from '@mielui/svelte/components/kbd';
</script>

<div class="grid place-items-center">
    <AlertDialog.Root error>
        <AlertDialog.Trigger variant="destructive">Delete project</AlertDialog.Trigger>
        <AlertDialog.Content size="md">
            <AlertDialog.Header>
                <AlertDialog.Title>Delete this project?</AlertDialog.Title>
                <AlertDialog.Description>
                    All branches, issues, and deploy history will be permanently removed.
                </AlertDialog.Description>
            </AlertDialog.Header>
            <AlertDialog.Footer>
                <AlertDialog.Close>
                    Cancel
                    <Kbd shortcut="esc" />
                </AlertDialog.Close>
                <AlertDialog.Confirm>
                    Delete project
                    <Kbd shortcut="enter" />
                </AlertDialog.Confirm>
            </AlertDialog.Footer>
        </AlertDialog.Content>
    </AlertDialog.Root>
</div>
~~~~

### Glass

~~~~svelte
<script lang="ts">
    import { Delete02Icon as Trash } from '@hugeicons/core-free-icons';
    import * as AlertDialog from '@mielui/svelte/components/alert-dialog';
    import Kbd from '@mielui/svelte/components/kbd';
    import HugeiconsIcon from '@mielui/svelte/hugeicons-icon';
</script>

<div class="grid place-items-center">
    <AlertDialog.Root error>
        <AlertDialog.Trigger variant="destructive">
            <HugeiconsIcon icon={Trash} size={14} />
            Delete workspace
        </AlertDialog.Trigger>
        <AlertDialog.Content surface="glass" size="md">
            <AlertDialog.Header>
                <div class="flex items-center gap-2.5">
                    <HugeiconsIcon icon={Trash} size={18} class="text-[var(--color-error)]" />
                    <AlertDialog.Title>Delete this workspace?</AlertDialog.Title>
                </div>
                <AlertDialog.Description>
                    All projects, comments, and exports will be removed. This action cannot be
                    undone.
                </AlertDialog.Description>
            </AlertDialog.Header>
            <AlertDialog.Footer>
                <AlertDialog.Close>
                    Cancel
                    <Kbd shortcut="esc" />
                </AlertDialog.Close>
                <AlertDialog.Confirm>
                    Delete
                    <Kbd shortcut="enter" />
                </AlertDialog.Confirm>
            </AlertDialog.Footer>
        </AlertDialog.Content>
    </AlertDialog.Root>
</div>
~~~~

### Hero

~~~~svelte
<script lang="ts">
    import { Delete02Icon as Trash } from '@hugeicons/core-free-icons';
    import * as AlertDialog from '@mielui/svelte/components/alert-dialog';
    import Kbd from '@mielui/svelte/components/kbd';
    import HugeiconsIcon from '@mielui/svelte/hugeicons-icon';

    let deleted = $state(false);

    function confirmDeletion() {
        deleted = true;
    }
</script>

<div class="flex flex-col items-center gap-3">
    <div class="grid place-items-center">
        <AlertDialog.Root error>
            <AlertDialog.Trigger variant="destructive">
                <HugeiconsIcon icon={Trash} size={14} />
                Delete workspace
            </AlertDialog.Trigger>
            <AlertDialog.Content size="md">
                <AlertDialog.Header>
                    <div class="flex items-center gap-2.5">
                        <HugeiconsIcon icon={Trash} size={18} class="text-[var(--color-error)]" />
                        <AlertDialog.Title>Delete this workspace?</AlertDialog.Title>
                    </div>
                    <AlertDialog.Description>
                        This preview will mark the sample workspace as deleted. Your actual
                        workspaces are unaffected.
                    </AlertDialog.Description>
                </AlertDialog.Header>
                <AlertDialog.Footer>
                    <AlertDialog.Close>
                        Cancel
                        <Kbd shortcut="esc" />
                    </AlertDialog.Close>
                    <AlertDialog.Confirm onclick={confirmDeletion}>
                        Delete
                        <Kbd shortcut="enter" />
                    </AlertDialog.Confirm>
                </AlertDialog.Footer>
            </AlertDialog.Content>
        </AlertDialog.Root>
    </div>

    <p role="status" class="text-sm text-foreground-muted">
        {deleted ? 'Sample workspace deleted.' : 'Sample workspace is active.'}
    </p>
</div>
~~~~

### Sign Out

~~~~svelte
<script lang="ts">
    import * as AlertDialog from '@mielui/svelte/components/alert-dialog';
    import Kbd from '@mielui/svelte/components/kbd';

    let signedOut = $state(false);

    function signOut() {
        signedOut = true;
    }
</script>

<div class="flex flex-col items-center gap-3">
    <div class="grid place-items-center">
        <AlertDialog.Root>
            <AlertDialog.Trigger variant="outline">Sign out</AlertDialog.Trigger>
            <AlertDialog.Content size="md">
                <AlertDialog.Header>
                    <AlertDialog.Title>Sign out?</AlertDialog.Title>
                    <AlertDialog.Description>
                        This preview will show a signed-out state. Your actual session is unchanged.
                    </AlertDialog.Description>
                </AlertDialog.Header>
                <AlertDialog.Footer>
                    <AlertDialog.Close>
                        Stay
                        <Kbd shortcut="esc" />
                    </AlertDialog.Close>
                    <AlertDialog.Confirm onclick={signOut}>
                        Sign out
                        <Kbd shortcut="enter" />
                    </AlertDialog.Confirm>
                </AlertDialog.Footer>
            </AlertDialog.Content>
        </AlertDialog.Root>
    </div>

    {#if signedOut}
        <p role="status" class="text-sm text-foreground-muted">Signed out of the preview.</p>
    {/if}
</div>
~~~~

For the rendered reference, visit [/docs/components/alert-dialog](/docs/components/alert-dialog).
