Dialog
Dialog opens a native modal panel, drawer, full-screen sheet or media view with a titled bar, a close button and a blurred backdrop.
01Preview
02Usage
Load @dg/ui/styles.css once in the root layout. Keep a reference with bind:this and open the dialog from a button.
<script>
import { Button, Dialog } from "@dg/ui";
/** @type {ReturnType<typeof Dialog>} */
let dialog;
let expanded = $state(false);
</script>
<Button
label="Filters"
aria-haspopup="dialog"
aria-controls="filters"
aria-expanded={expanded}
onclick={(event) => {
expanded = true;
dialog.open(event);
}}
/>
<Dialog bind:this={dialog} id="filters" title="Filters" placement="start" onclose={(event) => (expanded = event.currentTarget.open)}>
<p>Choose the works to display.</p>
</Dialog>
The media placement shows an image or other media over the blurred page. Controls placed in the content, such as previous and next buttons, take absolute positions in the band kept free around it.
<script>
import { Dialog } from "@dg/ui";
let { images } = $props();
let current = $state(0);
/** @type {ReturnType<typeof Dialog>} */
let dialog;
/** @param {number} index @param {MouseEvent} event */
function show(index, event) {
current = index;
dialog.open(event);
}
</script>
{#each images as image, index (image.src)}
<button type="button" onclick={(event) => show(index, event)}><img src={image.src} alt={image.alt} /></button>
{/each}
<Dialog
bind:this={dialog}
title="Gallery"
placement="media"
onkeydown={(event) => {
if (event.key === "ArrowRight") current = (current + 1) % images.length;
}}
>
<img src={images[current].src} alt={images[current].alt} />
</Dialog>
03Notes
- Native HTML attributes, DOM callbacks, class and style are forwarded to the dialog element. Use
idwith a trigger's aria-controls, and readevent.currentTarget.openinoncloseto follow the state: a dialog reopened right after closing can still receive the earlier close event. - Forwarding uses native attribute types; unknown props are not supported. Pass class as a string.
Dialogownsopenand its accessible name. - Panels and drawers scroll their content below a fixed bar. The full placement composes
Page: pass framed sections as children, give the last oneflex: 1to carry the frame rails to the bottom, and let the page scroll. - While the dialog is open, the document does not scroll. The backdrop is translucent and blurred, except in the full placement, which covers the page.
- The media placement is a transparent full-screen surface. Its title is visually hidden but still names the dialog, and the close button floats in a framed box at the top right. Content is centered and kept clear of a control-sized band on every side, reduced to a narrow inset at the inline edges below
--narrow; size media withmax-inline-size: 100%andmax-block-size: 100%. A press beside the content, on the surface itself, closes the dialog.
04Parameters
| Name | Type | Default | Description |
|---|---|---|---|
title | string | Required | Visible title in the dialog bar, hidden in the media placement, and accessible name of the dialog. |
placement | 'center' | 'start' | 'end' | 'full' | 'media' | "center" | Centered panel, full-height drawer from the inline start or end edge, opaque full-screen framed sheet, or transparent full-screen surface for media. |
closeLabel | string | undefined | Accessible name of the close button. Defaults to the built-in text in the Page language. |
children | Snippet | undefined | Dialog content. It renders only while the dialog is open, so its local state resets at each opening. |
05Overrides
| Name | Type | Default | Description |
|---|---|---|---|
--dialog-width | CSS length | 42rem (center), 26rem (start, end) | Preferred width of the centered panel and drawers, still limited by the viewport. Set it through style; full and media placements ignore it. |
06Methods
| Name | Description |
|---|---|
open() | Show the modal. Pass the activating click event so pointer entry focuses the panel; keyboard entry focuses the first control. |
close() | Close the modal. Escape, the close button and a press on the backdrop also close it; focus returns to the previously focused element. |
07Accessibility
Dialog uses the native modal dialog: content outside it is inert, Tab cycles inside it and Escape closes it. Its title names the dialog. Keyboard opening focuses the first control, normally the close button; pointer opening focuses the panel so the focus ring stays reserved for keyboard use. Closing returns focus to the trigger. When the content of a panel or drawer overflows, its scrolling body becomes a focusable region named by the title, so keyboard users can scroll long text that contains no controls; it draws its focus ring inside. The entry motion stops under reduced motion.