Built on the native <dialog> element: focus is trapped inside, Escape closes it,
page scroll is locked while it's open, and focus returns to the trigger on close.
Confirmation
Last event: none yet
Untitled and long content
Without a title, pass ariaLabel; the close button stays on the right.
CwDialog exampleCopy code
let open = $state(false);
<CwButton onclick={() => (open = true)}>Delete device</CwButton>
<CwDialog bind:open title="Delete device?">
<p>This removes the sensor and its history. This can't be undone.</p>
{#snippet actions()}
<CwButton variant="ghost" onclick={() => (open = false)}>Cancel</CwButton>
<CwButton variant="danger" onclick={remove}>Delete</CwButton>
{/snippet}
</CwDialog>
<!-- No visible title: give it an accessible name instead -->
<CwDialog bind:open={previewOpen} ariaLabel="Photo preview">…</CwDialog>
API
Usage and API reference
CwDialog wraps a native `<dialog>` element with the behavior most apps want by default: open state binding, title, actions, escape handling, and backdrop close.
How to think about it
Control visibility from the parentUse `bind:open` so the surrounding page decides when the dialog appears and disappears.
Put body content in `children` and footer buttons in `actions`This keeps the markup easy to scan and matches the built-in dialog layout.
Tighten close behavior only when neededLeave backdrop and escape close enabled unless the user must complete an explicit step.
Props and callbacks
API
Type
Details
open
Default: false
boolean
Dialog visibility state.
title
string
Title shown in the dialog header.
closeOnBackdrop
Default: true
boolean
Allows clicking the backdrop to close the dialog.
closeOnEscape
Default: true
boolean
Allows the Escape key to close the dialog.
children
Snippet
Main dialog content.
actions
Snippet
Footer actions row.
onclose
() => void
Runs whenever the dialog closes itself.
ariaLabel
string
Accessible name when the dialog has no visible `title`.
closeLabel
Default: 'Close dialog'
string
Accessible label for the close button.
hideClose
Default: false
boolean
Hides the close button (keep another way to close).
Copy-paste examples
Each snippet is a complete, working example you can paste into a Svelte 5 component.
Confirmation dialog
The parent owns the `open` state and the action buttons close the dialog explicitly.
Confirmation dialogCopy code
<script lang="ts">
let confirmOpen = $state(false);
</script>
<CwButton onclick={() => (confirmOpen = true)}>Delete zone</CwButton>
<CwDialog bind:open={confirmOpen} title="Delete zone">
{#snippet children()}
<p>This removes the zone and its alert rules.</p>
{/snippet}
{#snippet actions()}
<CwButton variant="ghost" onclick={() => (confirmOpen = false)}>Cancel</CwButton>
<CwButton variant="danger" onclick={() => (confirmOpen = false)}>Delete</CwButton>
{/snippet}
</CwDialog>
Blocking dialog
Only use this pattern when the user must complete an intentional workflow.