Skip to content
CodeAtlas UI

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
svelte
<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
svelte
<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
svelte
<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

PropTypeDefaultDescription
openbooleanfalseBindable open state.
titlestring–Required. Dialog title and accessible name.
descriptionstring–Supporting text below the title.
confirmLabelstring'Confirm' (localized)Label of the confirm button. Defaults to the active locale's string.
cancelLabelstring'Cancel' (localized)Label of the cancel button. Defaults to the active locale's string.
destructivebooleanfalseConfirm button uses the destructive variant.
pendingbooleanfalseControls 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.
classstring''Extra classes on the panel.