Dialog
A centered modal over a frosted backdrop that dims the page.
Basic
The .dialog root holds a .dialog__backdrop and a .dialog__panel wrapping the visible .dialog__content (header, body, footer, and a floating close chip). Open and close, focus trapping, scroll lock, and the static-backdrop shake come from the @stisla/vanilla layer: put data-stisla-dialog + an id on the root, point a data-stisla-dialog-trigger="id" button at it, and mark the backdrop and any close controls with data-stisla-dialog-dismiss. A header titles the dialog, the body carries the message, and the footer trails its actions. The close chip floats over the top-trailing corner. Add autofocus to any control inside the panel to land focus there on open. The demos below are live, each contained to its own frame.
Keyboard
Focus is trapped inside the dialog while it's open. On open, focus lands on the first element marked autofocus, falling back to .dialog__close; on close, focus returns to the trigger that opened it.
- Tab: cycle focus forward through focusable controls (wraps to the first)
- Shift + Tab: cycle focus backward (wraps to the last)
- Escape: dismiss the dialog (unless the backdrop is static, see Static backdrop below)
Scrollable body
Add .dialog__panel--scrollable so a long body scrolls while the header and footer stay pinned. The panel height is bounded to the viewport.
Fullscreen
.dialog--fullscreen drops the outer margin and corner radius so the panel takes the whole viewport, for immersive flows.
Sizes
Width modifiers on the root swap the panel size: the default sits mid-scale, with .dialog--sm, .dialog--lg, .dialog--xl, and .dialog--almost-fullscreen (a breathing strip around an otherwise full-viewport panel).
Positioning
The panel centers by default. .dialog__panel--top drops it in from above and .dialog__panel--bottom anchors it to the lower edge.
Static backdrop
Set data-stisla-dialog-backdrop="static" (with data-stisla-dialog-keyboard="false" to also block ESC) for a deliberate dismiss: a backdrop click shakes the panel instead of closing. Explicit dismiss controls still close.
Confirmation
The alert-dialog pattern for a destructive action: role="alertdialog", a tinted.icon-box for tone, a centered heading and description, and a Cancel / confirm pair. A small width keeps it focused.
Success
A celebratory end-of-flow state: the icon on top, the heading and description in the middle, and a single block button to the next step.
Media hero
Drop the header when the leading row is media. The floating close still sits at the top-trailing corner and reads against the image.
Lightbox
Override the surface variables on a single dialog to turn it into a frame for media. The blurred backdrop and the floating close carry the affordance.
Events
Four events fire on the .dialog root. The opening and closing events are cancelable.
stisla:dialog:opening fires before the panel mounts and the backdrop fades in. Call preventDefault() to abort (useful for an external readiness check).
stisla:dialog:opened fires once the open transition lands and focus is in place.
stisla:dialog:closing fires before the close transition starts. Call preventDefault() to keep it open (useful for unsaved-changes guards).
stisla:dialog:closed fires once the panel is fully hidden and focus has returned to the trigger.
Customization
These variables retune the dialog. Override on the root or any wrapper.
| Variable | Use |
|---|---|
--dialog-z-index | Overlay stacking order |
--dialog-width | Panel width cap; the size modifiers retune this |
--dialog-margin-block / -margin-inline | Gap between the panel and the viewport edges |
--dialog-bg / -color / -border-color | Content fill, text, and rim |
--dialog-radius / -shadow | Content corner radius and elevation |
--dialog-padding-block / -padding-inline | Header and body interior padding |
--dialog-title-font-size / -title-font-weight | Title type |
--dialog-footer-bg / -footer-border-color / -footer-padding-block | Footer seam fill, divider, and padding |
--dialog-backdrop-bg / -backdrop-blur | Scrim color and blur radius |
--dialog-close-size / -close-color / -close-bg / -close-bg-hover | Close chip size and frosted paint |
--dialog-transition-duration | Fade and scale timing; zeroed under reduced-motion |
Size modifiers set --dialog-width: .dialog--sm, .dialog--lg, .dialog--xl, plus .dialog--almost-fullscreen. Position the panel with .dialog__panel--top or .dialog__panel--bottom instead of the default center.