thermal-dialog
A modal dialog with a title, a close icon and a footer with a close button. The dialog opens when an element in its invoker slot is clicked. While it is open, the rest of the page is blurred and cannot be scrolled.
Attributes
label
Title displayed in the header of the dialog. When omitted, the header shows only the close icon.
<thermal-dialog label="Image details">
<thermal-btn slot="invoker">Open dialog</thermal-btn>
<div slot="content">The dialog title is set by the label attribute.</div>
</thermal-dialog>button
Text of the close button in the footer. When omitted, the text is a translation of "Close" in the current language of the webcomponents.
<thermal-dialog label="Information" button="Got it">
<thermal-btn slot="invoker">Open dialog</thermal-btn>
<div slot="content">The footer button says "Got it".</div>
</thermal-dialog>is-fullscreen
(if is-fullscreen is present, its value is true. If it is missing, its value is false. More info.)
Boolean attribute HTML examples
<!-- is-fullscreen is true in all of these cases: -->
<thermal-dialog is-fullscreen>Example</thermal-dialog>
<thermal-dialog is-fullscreen="">Example</thermal-dialog>
<thermal-dialog is-fullscreen="true">Example</thermal-dialog>
<thermal-dialog is-fullscreen="false">Example</thermal-dialog>
<thermal-dialog is-fullscreen="anything">Example</thermal-dialog>
<!-- is-fullscreen is false only when the attribute is missing: -->
<thermal-dialog>Example</thermal-dialog>When is-fullscreen is present, its Boolean property is true. However, the current fullscreen styles do not activate: Lit reflects this Boolean attribute as an empty value, while the CSS selector matches only the literal value "true". The attribute therefore currently has no visible fullscreen effect.
<thermal-dialog label="Fullscreen dialog" is-fullscreen>
<thermal-btn slot="invoker">Open fullscreen</thermal-btn>
<div slot="content">The Boolean property is enabled, but the current CSS selector prevents the fullscreen layout from appearing.</div>
</thermal-dialog>Standard global HTML attributes such as id or class work as on any other element.
Slots
<thermal-dialog label="All slots">
<thermal-btn slot="invoker">Open dialog</thermal-btn>
<div slot="content">The main content of the dialog.</div>
<thermal-btn slot="button" variant="primary">Extra button</thermal-btn>
</thermal-dialog>invoker– the element that opens the dialog when clicked, usually athermal-btn. It stays in the page where the dialog is placed. Athermal-btnwithdisableddoes not open the dialog.content– the body of the dialog. It is displayed only while the dialog is open.button– additional buttons in the footer, displayed before the close button. Clicking them does not close the dialog.
The close icon in the header and the close button in the footer close the dialog. The native <dialog> also closes on Escape; because the component does not handle the native cancel event, its open state can remain out of sync after that close.
JavaScript API
These members are available on the element once thermal-dialog is defined:
open– read-only,truewhile the dialog is open.setOpen()– opens the dialog.setClose()– closes the dialog immediately, without checkingbeforeClose.closeFromTheOutside()– closes the dialog. IfbeforeCloseis set, the dialog closes only when it resolves totrue.beforeClose– an optional async function returningtrueorfalse. It is checked by the footer close button and bycloseFromTheOutside(), but not by the close icon in the header.onCloseEveryTime– an optional function called wheneversetClose()closes the dialog.
beforeClose and onCloseEveryTime are functions, so they can be set only from JavaScript, not as HTML attributes.
Examples
After loading the webcomponents bundle as described in Usage in the browser, paste these examples directly into your HTML body.
Use a link as the invoker
Any HTML element can be placed in the invoker slot, not just a thermal-btn. This link opens the dialog; preventDefault() prevents navigation without stopping the click from reaching the slot. Prefer an interactive element such as a link or button so it can also be used with a keyboard.
<thermal-dialog label="Image details">
<a slot="invoker" href="#" onclick="event.preventDefault()">Show image details</a>
<div slot="content">This dialog was opened by an ordinary HTML link.</div>
</thermal-dialog>Confirm an action
A button in the button slot handles its click with the standard HTML onclick attribute. It writes the result next to the dialog and then closes the dialog.
<thermal-dialog label="Delete the file?" button="Cancel">
<thermal-btn slot="invoker">Delete file</thermal-btn>
<div slot="content">This action cannot be undone.</div>
<thermal-btn
slot="button"
variant="primary"
onclick="
const dialog = this.closest('thermal-dialog');
dialog.nextElementSibling.textContent = 'File deleted.';
dialog.closeFromTheOutside();
"
>
Delete
</thermal-btn>
</thermal-dialog>
<output aria-live="polite">Nothing deleted yet.</output>Complete HTML document
This example loads the webcomponents IIFE bundle and attaches a named function with addEventListener. Place the bundle at ./lib/labirthermal.iife.js relative to this HTML file, or adjust the script URL to its location.
The setup script deliberately appears before the dialog:
DOMContentLoadedwaits until the dialog, its buttons and the output exist in the DOM. Deferred scripts in the document head have also run.customElements.whenDefined('thermal-dialog')andcustomElements.whenDefined('thermal-btn')wait for both webcomponents to be registered, socloseFromTheOutside()is available.- Only then does the script attach the click listener.
DOMContentLoaded and whenDefined() ensure the document and custom elements are ready; they do not wait for component-specific asynchronous work such as fetching data.
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Dialog example</title>
<script defer src="./lib/labirthermal.iife.js"></script>
</head>
<body>
<script>
function confirmDelete() {
document.getElementById('delete-result').textContent = 'File deleted.';
document.getElementById('delete-dialog').closeFromTheOutside();
}
document.addEventListener('DOMContentLoaded', async () => {
await Promise.all([
customElements.whenDefined('thermal-dialog'),
customElements.whenDefined('thermal-btn'),
]);
const confirmButton = document.getElementById('confirm-delete');
confirmButton.addEventListener('click', confirmDelete);
});
</script>
<thermal-dialog id="delete-dialog" label="Delete the file?" button="Cancel">
<thermal-btn slot="invoker">Delete file</thermal-btn>
<div slot="content">This action cannot be undone.</div>
<thermal-btn id="confirm-delete" slot="button" variant="primary">
Delete
</thermal-btn>
</thermal-dialog>
<output id="delete-result" aria-live="polite">Nothing deleted yet.</output>
</body>
</html>The buttons can also be activated with Enter or Space when focused. This is a complete standalone document: copy it into your own HTML file to run it.