Feedback
AlertDialog
A confirmation dialog that demands an explicit answer, with role alertdialog and async confirm handling.
<script>
import { AlertDialog } from "@codeatlasdev/ui";
let open = $state(false);
</script>
<AlertDialog
bind:open
title="Delete item?"
description="This action cannot be undone."
confirmLabel="Delete"
destructive
onconfirm={() => api.remove(id)}
/>
Unlike Dialog, there is no close button and a click outside does not dismiss it. Escape and Cancel close it and fire oncancel. Both are ignored while a request is pending.
Basic and destructive
Confirm and cancel, with the destructive variant for irreversible actions.
Code
<script lang="ts">
import { AlertDialog, Button } from '@codeatlasdev/ui';
import { Trash2, LogOut } from '@lucide/svelte';
let signOutOpen = $state(false);
let deleteOpen = $state(false);
let log = $state<string[]>([]);
const push = (m: string) => (log = [m, ...log].slice(0, 4));
</script>
<Button variant="outlined" onclick={() => (signOutOpen = true)}>
{#snippet leading()}<LogOut size={14} />{/snippet}
Sign out
</Button>
<Button variant="destructive" onclick={() => (deleteOpen = true)}>
{#snippet leading()}<Trash2 size={14} />{/snippet}
Delete project
</Button>
<AlertDialog
bind:open={signOutOpen}
title="Sign out?"
description="You will need to sign in again to access your workspace."
confirmLabel="Sign out"
onconfirm={() => push('Signed out')}
oncancel={() => push('Sign out cancelled')}
/>
<AlertDialog
bind:open={deleteOpen}
title="Delete this project?"
description="This action cannot be undone. All data will be permanently removed."
confirmLabel="Delete"
destructive
onconfirm={() => push('Project deleted')}
/>
{#if log.length}
<ul class="log" aria-live="polite">
{#each log as entry, i (i + entry)}<li>{entry}</li>{/each}
</ul>
{/if}
<style>
.log {
flex-basis: 100%;
list-style: none;
margin: 0;
padding: 0;
display: grid;
gap: 4px;
font-size: 13px;
color: var(--ca-text-secondary);
}
</style>
Async onconfirm
While the promise is pending the confirm button shows a spinner, Cancel is disabled and Escape is ignored. The dialog closes when it resolves and stays open if it throws.
Code
<script lang="ts">
import { AlertDialog, Button } from '@codeatlasdev/ui';
let open = $state(false);
let done = $state(false);
const wait = (ms: number) => new Promise<void>((r) => setTimeout(r, ms));
async function removeItem() {
await wait(1500);
done = true;
}
</script>
<Button variant="destructive" onclick={() => ((done = false), (open = true))}>Remove item (1.5s)</Button>
<AlertDialog
bind:open
title="Remove item?"
description="The request takes 1.5 seconds."
confirmLabel="Remove"
destructive
onconfirm={removeItem}
/>
{#if done}<span class="note" aria-live="polite">Item removed (async onconfirm resolved).</span>{/if}
<style>
.note { font-size: 13px; color: var(--ca-text-secondary); }
</style>
Controlled pending
Pass pending when the loading state lives outside, for example a mutation from your query client.
Code
<script lang="ts">
import { AlertDialog, Button } from '@codeatlasdev/ui';
let open = $state(false);
let pending = $state(false);
async function publish() {
pending = true;
await new Promise<void>((r) => setTimeout(r, 1500));
pending = false;
open = false;
}
</script>
<Button variant="outlined" onclick={() => (open = true)}>Open controlled</Button>
<AlertDialog bind:open title="Publish changes?" confirmLabel="Publish" {pending} onconfirm={publish} />
Props
| Prop | Type | Default | Description |
|---|
open | boolean | false | Bindable open state. |
title | string | – | Required. Dialog title and accessible name. |
description | string | – | Supporting text below the title. |
confirmLabel | string | 'Confirm' (localized) | Label of the confirm button. Defaults to the active locale's string. |
cancelLabel | string | 'Cancel' (localized) | Label of the cancel button. Defaults to the active locale's string. |
destructive | boolean | false | Confirm button uses the destructive variant. |
pending | boolean | false | Controls the loading state externally. Without it, pending is automatic while onconfirm is awaited. |
onconfirm | () => void | Promise<void> | – | Required. Closes the dialog when it resolves; if it throws, the dialog stays open and the error is rethrown. |
oncancel | () => void | – | Fires on Cancel or Escape. Never fires while pending. |
class | string | '' | Extra classes on the panel. |