jolly-dialog ​
jolly-dialog wraps a native modal dialog and supplies a theme scope.
html
<jolly-dialog heading="Delete layer?">
<p>This cannot be undone.</p>
<jolly-button slot="actions">Cancel</jolly-button>
</jolly-dialog>Properties ​
ts
interface Dialog {
heading: string;
icon: IconName;
tone: IconTone | "";
intent: DialogIntent | "";
dismissible: boolean; // default true
headingEditable: boolean; // attribute heading-editable
readonly open: boolean;
readonly closing: boolean; // from close() until jolly-exited
}
type DialogIntent = "info" | "success" | "warning" | "danger";Events ​
ts
interface DialogEvents {
"jolly-cancel": undefined; // Escape or backdrop, when dismissible
"jolly-close": { returnValue: string; }; // exit transition starts
"jolly-exited": undefined; // exit transition ends
"jolly-heading-change": { heading: string; };
}- A dialog reopened before the exit transition ends emits no
jolly-exited. - Keep the body mounted until
jolly-exited, so it does not change while it fades out. An owner can also returnfalsefromshouldUpdatewhileclosingis true.
Methods ​
showModal(): Promise<void> ​
Opens the native dialog.
close(returnValue?: string): void ​
Closes it.
confirmInline(options: InlineConfirmOptions): Promise<boolean> ​
Asks for a confirmation inside the open dialog instead of stacking a second one. See Inline confirmation.
Slots and parts ​
- Slots: default (body),
actions(footer). - Parts:
header,icon,title,confirmation. - Body children stack in a column with
--jolly-space-2between them. Slottedp,ulandollose their block margins.
Icon, tone and intent ​
icondraws a registered glyph before the heading.tonemakes the dialog a toned area. Without one, it takes the tone of the nearestjolly-panearound it, shadow roots included, or the dock'ssharedTonewhen that pane's dock shares one. Outside a toned pane it takes the tone oficon. The pane is read on eachshowModal().intentcolours the header only, leaves the content on the accent, and wins overtone.DIALOG_INTENTSlists the intents.isDialogIntent(value)narrows a string.- Under forced colours the header uses system colours and the icon carries the intent.
Each intent paints the header with --jolly-intent-<intent>-fill and has a default icon, which an explicit icon replaces:
info: iconinfo, roledialog.success: iconcheck, roledialog.warning: iconwarning, rolealertdialog.danger: iconwarning, rolealertdialog.
html
<jolly-dialog heading="Delete layer?" intent="danger"></jolly-dialog>Editable heading ​
With heading-editable, the heading is a text input in the header.
- Enter or blur commits a trimmed value that differs from
heading, asjolly-heading-change. An empty or unchanged draft emits nothing. - Escape reverts the input and leaves the dialog open.
- The dialog does not write
heading: the owner applies the new name. - The dialog opens with focus on itself, not on the input.
Inline confirmation ​
ts
interface InlineConfirmOptions {
message: string;
confirmLabel?: string; // default "OK"
cancelLabel?: string; // default "Cancel"
danger?: boolean;
}
const confirmed = await dialog.confirmInline({
message: "3 blocks use this blockset and will lose their texture.",
confirmLabel: "Remove",
danger: true
});- Resolves
trueon confirm,falseon cancel, Escape, backdrop click or close. On a closed dialog it resolvesfalse. - The footer shows the message and its two buttons. The body is inert and the
actionsslot hidden. - The confirm button takes focus and is the default action. Focus returns when the confirmation settles.
dangeruses thedangerbutton variant and tints the footer.- Escape answers
falseand keeps the dialog open. A second Escape closes it. - With no dialog open, use
showConfirm().
Default action ​
Enter activates the actions element with data-default, otherwise the last one with variant accent or danger.
html
<jolly-button slot="actions">Cancel</jolly-button>
<jolly-button slot="actions" variant="accent" data-default>Create</jolly-button>- A disabled candidate, or none, leaves Enter alone.
- Buttons, links, textareas and contenteditable content keep Enter.
- Fields such as
jolly-textcommit their draft first, so the action sees the typed value.
Keyboard scope ​
An open dialog holds an input layer. inputLayers.dismissAll() cancels it like Escape, unless dismissible is false.
Styling ​
--jolly-dialog-header-bg: header fill, default--jolly-accent-fill.--jolly-dialog-chrome-bg: footer fill, default--jolly-inkat 4% over--jolly-surface-raised.--jolly-dialog-chrome-padding: header and footer padding, defaultcalc(var(--jolly-row-height) * 0.4).--jolly-dialog-backdrop: default--jolly-dialog-header-bgat 28% over--jolly-scrim, so it follows the accent, tone or intent.--jolly-dialog-backdrop-filter: defaultblur(2px).- A dialog that previews edits on the page behind it can set
--jolly-dialog-backdrop-filter: none.
Motion ​
css
:root {
--jolly-duration-enter: 250ms;
--jolly-duration-exit: 150ms;
--jolly-easing-overlay: cubic-bezier(0.22, 1, 0.36, 1);
--jolly-overlay-scale: 0.96;
}- The dialog and its backdrop fade and scale in and out.
jolly-context-menuand field popovers use the same motion, scaled from the edge nearest their anchor.prefers-reduced-motion: reducedisables the transitions.