Dialog ported
A focused surface for decisions that need attention.
A modal overlay and panel with a titled header, built-in close button, accessible focus trap, and interruptible spring transitions.
Loading demo…
Guidance
When to use
- Confirmations and decisions that must interrupt, such as Delete project.
- Short forms like rename or invite that fit in one focused panel.
- Flows where the dialog title changes between steps and should crossfade in place.
When not to use
- Use Drawer for long forms or detail panels that keep the page in context.
- Use Bottom Sheet for mobile-first secondary tasks with snap heights.
- Use Popover for light, non-modal content anchored to a trigger.
pnpm dlx shadcn-svelte@latest add @arcui/dialogUsage
<script lang="ts">
import { Dialog, DialogTrigger, DialogContent, DialogClose } from '$lib/components/dialog';
</script>
<Dialog>
<DialogTrigger class="btn-primary">Rename project</DialogTrigger>
<DialogContent title="Rename project" description="This updates the project URL across your team.">
<div class="form-body">
<label for="name">Project Name</label>
<input id="name" type="text" value="Arc UI Svelte" />
</div>
<div class="dialog-actions">
<DialogClose class="btn-secondary">Cancel</DialogClose>
<DialogClose class="btn-primary">Save Changes</DialogClose>
</div>
</DialogContent>
</Dialog>Variants & Examples
Standard Modal Dialog
Uncontrolled dialog triggered by a nested button with title and description.
<Dialog>
<DialogTrigger>Open Dialog</DialogTrigger>
<DialogContent title="Quick Action" description="Perform an immediate action.">
<p>Dialog body content.</p>
</DialogContent>
</Dialog>Controlled Two-Way Binding
Controlled visibility using Svelte 5 bind:open rune.
<script lang="ts">
let isModalOpen = $state(false);
</script>
<Dialog bind:open={isModalOpen}>
<DialogTrigger>Configure</DialogTrigger>
<DialogContent title="Configuration">
<p>Settings panel</p>
</DialogContent>
</Dialog>Destructive Confirmation
Dialog focused on irreversible actions with clear cancel and confirm paths.
<Dialog>
<DialogTrigger class="btn-danger">Delete</DialogTrigger>
<DialogContent title="Delete Project?" description="This action cannot be undone.">
<div class="actions">
<DialogClose>Cancel</DialogClose>
<DialogClose class="btn-danger">Confirm Delete</DialogClose>
</div>
</DialogContent>
</Dialog>API Reference
| Prop | Type | Default | Description |
|---|---|---|---|
title | string | — | Dialog title, rendered as Dialog.Title. In Phase 2, title changes crossfade in place. |
description | string | — | Optional supporting line, rendered as Dialog.Description. |
open | boolean | — | Controlled open state. Supports two-way bind:open. |
defaultOpen | boolean | false | Initial open state when uncontrolled. |
onOpenChange | (open: boolean) => void | — | Called when the dialog opens or closes. |
onInteractOutside | (event: PointerEvent) => void | — | Callback when clicking outside the dialog content. |
children | Snippet | — | Modal body content rendered below header and above close button. |
ref | HTMLElement | null | — | Bindable ref to the underlying Dialog.Content element. |
Keyboard Interactions
| Key | Action |
|---|---|
Escape | Closes the dialog and returns focus cleanly to the trigger. |
Tab / Shift+Tab | Cycles focus trapped strictly within the active dialog modal. |
Accessibility
- Bits UI renders role="dialog" with aria-modal="true", traps focus, and restores it cleanly to the trigger on close.
- title and description automatically link to aria-labelledby and aria-describedby.
- The built-in close button carries aria-label="Close dialog".
Motion
Phase 1 still-state: overlay and panel render their static rest and leave end-states with visibility toggles. Phase 2 springs the overlay fade and panel 8px rise / 0.96 scale with interruptible retargeting. Reduced motion uses a plain opacity fade.
Notes for AI
- Use for decisions that must interrupt: confirmations, short forms. Use Drawer for side panels, Bottom Sheet for mobile-first secondary tasks, Popover for light non-modal content.
- Always compose Dialog with DialogTrigger, DialogContent, and optional DialogClose.
Source of truth: registry/components/dialog/dialog.tsx