Dialogs are modal windows built on the native <dialog> element. They trap focus, darken the backdrop, and support header, body, and footer sections. Opening and closing is handled via data-dialog-open and data-dialog-close attributes.
Basic usage
<button class="button" type="button" data-dialog-open="my-dialog">Open dialog</button>
<dialog id="my-dialog" class="dialog">
<div class="dialog-header">
<h3 class="dialog-title">Dialog title</h3>
<button class="dialog-close" type="button" aria-label="Close"><!-- close icon --></button>
</div>
<div class="dialog-body">
<p>Dialog content here.</p>
</div>
<div class="dialog-footer">
<button class="button" data-variant="faded" type="button" data-dialog-close>Cancel</button>
<button class="button" type="button" data-dialog-close>Confirm</button>
</div>
</dialog>
Confirmation dialog
A destructive action pattern with a danger-styled confirm button.
JavaScript
Include assets/js/dialog.js on any page using dialogs.
<script src="/assets/js/dialog.js"></script>
data-dialog-open="dialog-id"on a trigger opens the dialog viashowModal()data-dialog-closeor inside a dialog closes it- Clicking the backdrop also closes the dialog
Keyboard interactions
| Key | Action |
|---|---|
Escape |
Closes the dialog |
Tab |
Cycles through focusable elements inside the dialog (focus is trapped) |
Enter / Space |
Activates the focused button |
Accessibility
- Uses the native
<dialog>element — focus trapping is handled by the browser - The dialog title should use
aria-labelledbypointing to the ID - Close buttons must have
aria-label="Close" - The backdrop is created by the browser's
::backdroppseudo-element
Usage rules
Do:
- Use dialogs for actions that require confirmation or focused input
- Keep dialog content concise — one task per dialog
- Always provide a way to dismiss (close button + Escape + backdrop click)
Don't:
- Don't use dialogs for content that should be inline on the page
- Don't stack dialogs on top of each other
- Don't use dialogs for simple alerts — use callouts or toasts instead
CSS reference
This section documents how the component is built. For usage, see the sections above.
Tokens
| Token | Default (Light) | Default (Dark) | What it controls |
|---|---|---|---|
| Dialog surface | |||
560px |
— | Maximum width | |
0 8px 32px var(--black-alpha-20) |
0 8px 40px var(--black-alpha-60) |
Drop shadow | |
rgba(0, 0, 0, 0.6) |
— | Backdrop overlay |
Selectors
| Selector | Purpose |
|---|---|
| Base component — background, max-width, shadow, border, padding | |
.dialog::backdrop |
Backdrop overlay colour |
.dialog[open] |
Open state — opacity transition for entrance animation |
| Flex row for title + close button | |
| Dialog heading | |
| Close button (icon button reset) | |
.dialog-close:hover |
Close button hover — text colour change |
.dialog-close:focus-visible |
Close button focus ring |
| Content area with vertical padding | |
| Footer with flex-end alignment for action buttons | |
[data-theme="dark"] .dialog |
Dark mode overrides for background and shadow |