Dialog
A modal dialog overlay with focus trap, scroll lock, and accessible markup.
bun x bosia@latest add dialogA modal dialog that overlays the page with a backdrop, traps focus, locks body scroll, and closes on Escape or backdrop click. Fully accessible with role="dialog", aria-modal, aria-labelledby, and aria-describedby.
Preview
Props
DialogContent
| Prop | Type | Default |
|---|---|---|
closeOnBackdropClick |
boolean |
true |
class |
string |
"" |
Dialog
| Prop | Type | Default |
|---|---|---|
open |
boolean |
false |
Sub-components
Dialog— root context provider, manages open stateDialogTrigger— button that toggles the dialog openDialogContent— fixed overlay + panel with focus trap and animationsDialogClose— wraps any element to close on clickDialogHeader— flex container for title areaDialogTitle—<h2>linked viaaria-labelledbyDialogDescription— muted text linked viaaria-describedbyDialogFooter— footer with action buttons layout
Usage
<script lang="ts">
import {
Dialog,
DialogTrigger,
DialogContent,
DialogHeader,
DialogTitle,
DialogDescription,
DialogFooter,
DialogClose,
} from "$lib/components/ui/dialog";
import { Button } from "$lib/components/ui/button";
</script>
<Dialog>
<DialogTrigger>
<Button variant="outline">Open Dialog</Button>
</DialogTrigger>
<DialogContent>
<DialogHeader>
<DialogTitle>Are you sure?</DialogTitle>
<DialogDescription>This action cannot be undone.</DialogDescription>
</DialogHeader>
<DialogFooter>
<DialogClose>
<Button variant="outline">Cancel</Button>
</DialogClose>
<Button>Confirm</Button>
</DialogFooter>
</DialogContent>
</Dialog>Controlled Open State
<script lang="ts">
let open = $state(false);
</script>
<Dialog bind:open>
<DialogTrigger>
<Button>Open</Button>
</DialogTrigger>
<DialogContent>
<DialogHeader>
<DialogTitle>Controlled Dialog</DialogTitle>
</DialogHeader>
<p>You can control this dialog programmatically.</p>
</DialogContent>
</Dialog>
<p>Dialog is {open ? "open" : "closed"}</p>Disable Backdrop Close
<DialogContent closeOnBackdropClick={false}>
<!-- Only closes via Escape key or DialogClose button -->
</DialogContent>Accessibility
role="dialog"andaria-modal="true"on the content panelaria-labelledbylinked toDialogTitlearia-describedbylinked toDialogDescription- Focus is trapped inside the dialog (Tab cycles through focusable elements)
- Focus returns to the trigger element when the dialog closes
- Escape key closes the dialog
- Body scroll is locked while open