Dialog
A modal <dialog> whose opening and closing are animated, while showModal(), the focus trap, Esc, returnValue and focus restore stay native.
Live example: two layouts
Usage
<dialog id="confirm" closedby="any" aria-labelledby="confirm-title">
<div class="panel" data-fx-panel>
<form method="dialog">
<h2 id="confirm-title">Save changes?</h2>
<button value="cancel">Cancel</button>
<button value="ok">Save</button>
</form>
</div>
</dialog>
import { createRenderer, createDialogFx, inkVeilEffect } from 'webgl-ui'
import 'webgl-ui/src/elements/dialog/dialog.css' // the CSS contract
const renderer = createRenderer()
const dialog = document.querySelector<HTMLDialogElement>('#confirm')!
// Register your own `cancel` listeners BEFORE this line: whoever vetoes the close first wins.
createDialogFx(dialog, { renderer, effect: inkVeilEffect, layout: 'behind' })
dialog.showModal() // same signature as the native method, now animated
Options
| Option | Type | Default | Description |
|---|---|---|---|
renderer | Renderer | () => Renderer | required | The shared renderer. |
effect | EffectDef | backdropEffect | With 'viewport' or 'behind' a veil such as inkVeilEffect; with 'host' a cover such as inkEffect. |
layout | 'viewport' | 'behind' | 'host' | 'viewport' | viewport: the effect is the backdrop. behind: the effect paints the panel's sheet behind its content, so the dialog appears from nothing. host: the effect covers the dialog box. With behind and host the backdrop is CSS. |
duration | number | 1200 | Opening in ms; closing takes 65%. |
keepBackdrop | boolean | false | viewport only: after the opening the effect keeps moving for drift ms, slowing to a stop; then its still frame becomes the ::backdrop image, for backdrops CSS cannot draw (noise, halftone). The canvas still goes away. |
drift | number | 3500 | With keepBackdrop: how long the backdrop keeps moving after the opening. Opening plus drift stay under five seconds by default (WCAG 2.2.2). |
paintsPanel | boolean | false | viewport only: the effect also paints the panel's sheet (it gets uPanel and uSheet); the panel is transparent while animating. |
trace | (message) => void | none | Debug hook. |
Returns
| Member | Description |
|---|---|
showModal() | Native call, synchronous (same errors), then the animation. Also installed on the element. |
close(returnValue?) | Animated; the native close() runs at the end, with the close event and focus restore. |
destroy() | Restores the native methods and removes the listeners. |
debug() | { open, target, running, progress }. |
CSS contract
Import src/elements/dialog/dialog.css or copy it. It expects:
| Hook | Meaning |
|---|---|
[data-fx-panel] | The visible surface, inside a transparent <dialog> box. |
--fx-rgb, --fx-a | Backdrop color and alpha, read by both CSS and shader, so the hand-over at the end is invisible. |
[data-animating], --p | Set on the dialog while animating. |
[data-fx-host] | Present with behind and host: the backdrop fades in with --p. |
[data-fx-behind] | Present with behind: the panel's background is transparent while animating, the shader paints it. |
--fx-cover | The color the shader paints with behind and host (and uSheet with paintsPanel): set it to the panel's background. |
[data-fx-snapshot], --fx-backdrop-image | With keepBackdrop: the backdrop shows the still frame (redrawn if the window is resized). Removed when the dialog closes. |
[data-fx-ambient] | With keepBackdrop, while the backdrop drifts to a stop: the canvas still draws it, the ::backdrop is transparent. |
Behavior and accessibility
- Top layer,
inert, focus trap and initial focus are native and start synchronously withshowModal(). - Esc,
closedby,requestClose()and<form method="dialog">are intercepted only to animate; an earlierpreventDefaultoncancelwins. - While closing,
openstaystrue;closeand focus restore arrive at the end. commandforbuttons withcommand="show-modal"or"close"are animated (the button'svaluebecomesreturnValue);"request-close"goes throughcancel.show()(non-modal) is not wrapped.
Full table: native parity, dialog.