Kern 0.12.0 GitHub
Feedback

<kern-dialog>

Modal dialog for confirmations and short forms, on the native <dialog>. Destructive: the heading names action and device, a kern-alert tone="warn" states the consequence, the confirm button is variant="danger" with a verb.

Examples

Confirmation dialog

A modal dialog on the native <dialog>: show() opens it, close(returnValue) closes it and kernClose reports the value. Escape and × close it unless dismissible="false". Footer buttons: cancel first, confirm last.

Restart …

Küche Licht will be unreachable for about 10 seconds.

Cancel Restart
<kern-button class="open">Restart …</kern-button> <p class="out" style="font-size:13px;color:var(--text-muted)"></p> <kern-dialog heading="Restart Küche Licht?"> <p>Küche Licht will be unreachable for about 10 seconds.</p> <kern-button slot="footer" class="cancel">Cancel</kern-button> <kern-button slot="footer" variant="primary" class="ok">Restart</kern-button> </kern-dialog> const dialog = root.querySelector('kern-dialog'); root.querySelector('.open').addEventListener('click', () => dialog.show()); root.querySelector('.cancel').addEventListener('click', () => dialog.close('cancel')); root.querySelector('.ok').addEventListener('click', () => dialog.close('ok')); dialog.addEventListener('kernClose', (e) => (root.querySelector('.out').textContent = `kernClose → ${e.detail.returnValue}`));

Destructive action

The heading names the action and the device, a kern-alert with tone="warn" states the consequence, and the confirm button is variant="danger" with a verb. width sets the panel width in px.

Factory reset … The device loses its configuration and starts in AP mode. Cancel Reset
<kern-button class="open" variant="danger">Factory reset …</kern-button> <kern-dialog heading="Factory reset «Küche Licht»" width="440"> <kern-alert tone="warn">The device loses its configuration and starts in AP mode.</kern-alert> <kern-button slot="footer" class="cancel">Cancel</kern-button> <kern-button slot="footer" variant="danger" class="ok">Reset</kern-button> </kern-dialog> const dialog = root.querySelector('kern-dialog'); root.querySelector('.open').addEventListener('click', () => dialog.show()); root.querySelector('.cancel').addEventListener('click', () => dialog.close('cancel')); root.querySelector('.ok').addEventListener('click', () => dialog.close('reset'));

confirm()

confirm(), imported from '@yfridelance/kern', builds the dialog for you and resolves true on confirm, false otherwise. danger styles the confirm button; with typeToConfirm it stays disabled until that text (e.g. the MAC) is typed. Pass an array to accept any one of several answers, e.g. the device name or its MAC.

The typed text and every alternative go through normalize before comparing: by default trim() and upper case. normalize: 'mac' accepts a MAC in any notation (A8:03:2A:B1:23:45, a8-03-2a-b1-23-45, A8032AB12345) and treats other text like the default; your own (text) => string works too. The default label lists all alternatives («Type “Boiler” or “A8:03:2A:B1:23:45” to confirm» in the Kern language, MACs formatted with 'mac'); typeToConfirmLabel overrides it.

Restart Bad Lüftung Factory reset … Delete Boiler …

<div style="display:flex;flex-wrap:wrap;gap:12px"> <kern-button class="restart">Restart Bad Lüftung</kern-button> <kern-button class="reset" variant="danger">Factory reset …</kern-button> <kern-button class="delete" variant="danger">Delete Boiler …</kern-button> </div> <p class="out" style="font-size:13px;color:var(--text-muted)"></p> const { confirm } = await import('../kern/index.esm.js'); const out = root.querySelector('.out'); root.querySelector('.restart').addEventListener('click', async () => { const ok = await confirm({ heading: 'Restart Bad Lüftung?', message: 'The fan stops for about 10 seconds.', confirmLabel: 'Restart' }); out.textContent = `confirm → ${ok}`; }); root.querySelector('.reset').addEventListener('click', async () => { const ok = await confirm({ heading: 'Factory reset «Küche Licht»', message: 'The device starts in AP mode afterwards.', confirmLabel: 'Reset', danger: true, typeToConfirm: 'A4CF12F45B21', typeToConfirmLabel: 'Type the MAC A4CF12F45B21 to confirm', }); out.textContent = `confirm → ${ok}`; }); root.querySelector('.delete').addEventListener('click', async () => { // Name or MAC, the MAC in any notation (a8-03-2a-b1-23-45, A8032AB12345 …). const ok = await confirm({ heading: 'Delete «Boiler»?', confirmLabel: 'Delete', danger: true, typeToConfirm: ['Boiler', 'a8032ab12345'], normalize: 'mac', }); out.textContent = `confirm → ${ok}`; });

Start in a field

autofocus on a Kern field moves the focus there when the dialog opens, instead of to the close button. Native controls with autofocus work as in a plain <dialog>. kernOpen fires after opening; without autofocus, set the focus there with the field's setFocus().

Add scene … Cancel Add
<kern-button class="open">Add scene …</kern-button> <kern-dialog heading="Add scene"> <kern-input label="Name" placeholder="Evening" autofocus></kern-input> <kern-button slot="footer" class="cancel">Cancel</kern-button> <kern-button slot="footer" variant="primary" class="ok">Add</kern-button> </kern-dialog> const dialog = root.querySelector('kern-dialog'); root.querySelector('.open').addEventListener('click', () => dialog.show()); root.querySelector('.cancel').addEventListener('click', () => dialog.close('cancel')); root.querySelector('.ok').addEventListener('click', () => dialog.close('ok'));

Properties

closeLabelattribute close-label · default Close · de Schliessen
string | undefined

Accessible label of the close button.

dismissibledefault true
boolean

Shows the close button and allows Escape.

heading
string | undefined
label
string | undefined

Accessible name of the dialog when it has no visible heading.

openmutablereflectsdefault false
boolean
widthdefault 520
number

Panel width in px.

Events

kernClose
CustomEvent<{ returnValue: string; }>

After the dialog closed (Escape, close button or close()); detail.returnValue as given to close().

kernOpen
CustomEvent<void>

After the dialog opened (show() or open). The focus moves to the first Kern field with autofocus once it is ready, otherwise it stays on the first focusable element (the close button); without autofocus the app can set it here.

Methods

close()
close(returnValue?: string) => Promise<void>

Closes the dialog; returnValue is passed to kernClose.

show()
show() => Promise<void>

Opens the dialog modally.

Slots

(default)

Body

footer

Buttons, right-aligned: cancel first, confirm last

CSS parts

panel

The dialog surface