Dialog
Overlay primitive that coordinates native dialog behavior with shared overlay stack rules.
Default
Without modal a dialog is non-modal, like native show(): the rest of the page stays usable and the header close button is its exit. Label becomes the header title beside that button. Buttons in the actions slot sit right-aligned in the footer, secondary first and primary last; native command="close" closes the dialog.
Code
<link
rel="component"
href="@threadlabs/looma/components/ui-button/ui-button.html"
>
<link
rel="component"
href="@threadlabs/looma/components/ui-dialog/ui-dialog.html"
>
<ui-button
id="open-confirmation"
>Review Fellowship memo</ui-button>
<ui-dialog
id="confirmation-dialog"
for="open-confirmation"
label="Send Fellowship memo?"
>
<p>Frodo and Sam will receive the updated route. Sméagol is keeping the meeting notes.</p>
<ui-button
slot="actions"
commandfor="confirmation-dialog"
command="close"
>Keep draft</ui-button>
<ui-button
slot="actions"
variant="solid"
commandfor="confirmation-dialog"
command="close"
>Send memo</ui-button>
</ui-dialog><script setup>
import { UiButton, UiDialog } from "@threadlabs/looma";
</script>
<template>
<UiButton
id="open-confirmation"
>Review Fellowship memo</UiButton>
<UiDialog
id="confirmation-dialog"
for="open-confirmation"
label="Send Fellowship memo?"
>
<p>Frodo and Sam will receive the updated route. Sméagol is keeping the meeting notes.</p>
<template #actions>
<UiButton
commandfor="confirmation-dialog"
command="close"
>Keep draft</UiButton>
<UiButton
variant="solid"
commandfor="confirmation-dialog"
command="close"
>Send memo</UiButton>
</template>
</UiDialog>
</template>import { UiButton, UiDialog } from "@threadlabs/looma";
export default function Example() {
return <>
<UiButton
id="open-confirmation"
>Review Fellowship memo</UiButton>
<UiDialog
id="confirmation-dialog"
htmlFor="open-confirmation"
label="Send Fellowship memo?"
slots={{
actions: <>
<UiButton
commandfor="confirmation-dialog"
command="close"
>Keep draft</UiButton>
<UiButton
variant="solid"
commandfor="confirmation-dialog"
command="close"
>Send memo</UiButton>
</>,
}}
>
<p>Frodo and Sam will receive the updated route. Sméagol is keeping the meeting notes.</p>
</UiDialog>
</>;
}/** @jsxImportSource preact */
import { UiButton, UiDialog } from "@threadlabs/looma";
export default function Example() {
return <>
<UiButton
id="open-confirmation"
>Review Fellowship memo</UiButton>
<UiDialog
id="confirmation-dialog"
htmlFor="open-confirmation"
label="Send Fellowship memo?"
slots={{
actions: <>
<UiButton
commandfor="confirmation-dialog"
command="close"
>Keep draft</UiButton>
<UiButton
variant="solid"
commandfor="confirmation-dialog"
command="close"
>Send memo</UiButton>
</>,
}}
>
<p>Frodo and Sam will receive the updated route. Sméagol is keeping the meeting notes.</p>
</UiDialog>
</>;
}<script>
import { UiButton, UiDialog } from "@threadlabs/looma";
</script>
{#snippet actions()}
<UiButton
commandfor="confirmation-dialog"
command="close"
>Keep draft</UiButton>
<UiButton
variant="solid"
commandfor="confirmation-dialog"
command="close"
>Send memo</UiButton>
{/snippet}
<UiButton
id="open-confirmation"
>Review Fellowship memo</UiButton>
<UiDialog
id="confirmation-dialog"
for="open-confirmation"
label="Send Fellowship memo?"
slots={{ actions }}
>
<p>Frodo and Sam will receive the updated route. Sméagol is keeping the meeting notes.</p>
</UiDialog>import { Component } from "@angular/core";
import { UiButton, UiDialog } from "@threadlabs/looma";
@Component({
selector: "example-view",
standalone: true,
imports: [UiButton, UiDialog],
template: `
<ng-template
ui-button
[hnAttributes]="{ id: 'open-confirmation' }"
>Review Fellowship memo</ng-template>
<dialog
ui-dialog
id="confirmation-dialog"
[for]="'open-confirmation'"
[label]="'Send Fellowship memo?'"
>
<p>Frodo and Sam will receive the updated route. Sméagol is keeping the meeting notes.</p>
<ng-container ngProjectAs="[slot='actions']">
<ng-template
ui-button
[hnAttributes]="{ commandfor: 'confirmation-dialog', command: 'close' }"
>Keep draft</ng-template>
<ng-template
ui-button
[variant]="'solid'"
[hnAttributes]="{ commandfor: 'confirmation-dialog', command: 'close' }"
>Send memo</ng-template>
</ng-container>
</dialog>
`,
})
export default class Example {}modal
Modal opens the dialog in the top layer over a backdrop and makes the rest of the page inert until it closes.
Code
<link
rel="component"
href="@threadlabs/looma/components/ui-button/ui-button.html"
>
<link
rel="component"
href="@threadlabs/looma/components/ui-dialog/ui-dialog.html"
>
<ui-button
id="open-modal-dialog"
>Open modal dialog</ui-button>
<ui-dialog
id="modal-dialog"
for="open-modal-dialog"
modal
label="Delete project?"
>
<p>This permanently removes the project and its history.</p>
<ui-button
slot="actions"
commandfor="modal-dialog"
command="close"
>Cancel</ui-button>
<ui-button
slot="actions"
variant="danger"
commandfor="modal-dialog"
command="close"
>Delete</ui-button>
</ui-dialog><script setup>
import { UiButton, UiDialog } from "@threadlabs/looma";
</script>
<template>
<UiButton
id="open-modal-dialog"
>Open modal dialog</UiButton>
<UiDialog
id="modal-dialog"
for="open-modal-dialog"
:modal="true"
label="Delete project?"
>
<p>This permanently removes the project and its history.</p>
<template #actions>
<UiButton
commandfor="modal-dialog"
command="close"
>Cancel</UiButton>
<UiButton
variant="danger"
commandfor="modal-dialog"
command="close"
>Delete</UiButton>
</template>
</UiDialog>
</template>import { UiButton, UiDialog } from "@threadlabs/looma";
export default function Example() {
return <>
<UiButton
id="open-modal-dialog"
>Open modal dialog</UiButton>
<UiDialog
id="modal-dialog"
htmlFor="open-modal-dialog"
modal
label="Delete project?"
slots={{
actions: <>
<UiButton
commandfor="modal-dialog"
command="close"
>Cancel</UiButton>
<UiButton
variant="danger"
commandfor="modal-dialog"
command="close"
>Delete</UiButton>
</>,
}}
>
<p>This permanently removes the project and its history.</p>
</UiDialog>
</>;
}/** @jsxImportSource preact */
import { UiButton, UiDialog } from "@threadlabs/looma";
export default function Example() {
return <>
<UiButton
id="open-modal-dialog"
>Open modal dialog</UiButton>
<UiDialog
id="modal-dialog"
htmlFor="open-modal-dialog"
modal
label="Delete project?"
slots={{
actions: <>
<UiButton
commandfor="modal-dialog"
command="close"
>Cancel</UiButton>
<UiButton
variant="danger"
commandfor="modal-dialog"
command="close"
>Delete</UiButton>
</>,
}}
>
<p>This permanently removes the project and its history.</p>
</UiDialog>
</>;
}<script>
import { UiButton, UiDialog } from "@threadlabs/looma";
</script>
{#snippet actions()}
<UiButton
commandfor="modal-dialog"
command="close"
>Cancel</UiButton>
<UiButton
variant="danger"
commandfor="modal-dialog"
command="close"
>Delete</UiButton>
{/snippet}
<UiButton
id="open-modal-dialog"
>Open modal dialog</UiButton>
<UiDialog
id="modal-dialog"
for="open-modal-dialog"
modal
label="Delete project?"
slots={{ actions }}
>
<p>This permanently removes the project and its history.</p>
</UiDialog>import { Component } from "@angular/core";
import { UiButton, UiDialog } from "@threadlabs/looma";
@Component({
selector: "example-view",
standalone: true,
imports: [UiButton, UiDialog],
template: `
<ng-template
ui-button
[hnAttributes]="{ id: 'open-modal-dialog' }"
>Open modal dialog</ng-template>
<dialog
ui-dialog
id="modal-dialog"
[for]="'open-modal-dialog'"
[modal]="true"
[label]="'Delete project?'"
>
<p>This permanently removes the project and its history.</p>
<ng-container ngProjectAs="[slot='actions']">
<ng-template
ui-button
[hnAttributes]="{ commandfor: 'modal-dialog', command: 'close' }"
>Cancel</ng-template>
<ng-template
ui-button
[variant]="'danger'"
[hnAttributes]="{ commandfor: 'modal-dialog', command: 'close' }"
>Delete</ng-template>
</ng-container>
</dialog>
`,
})
export default class Example {}Outside dismissal
A modal dialog closes on Escape by default; closedby="any" also closes it after a press outside.
Code
<link
rel="component"
href="@threadlabs/looma/components/ui-button/ui-button.html"
>
<link
rel="component"
href="@threadlabs/looma/components/ui-dialog/ui-dialog.html"
>
<ui-button
id="open-dismissible-dialog"
>Open dismissible dialog</ui-button>
<ui-dialog
id="dismissible-dialog"
for="open-dismissible-dialog"
modal
closedby="any"
label="Keyboard shortcuts"
>
<p>Press <kbd>Escape</kbd> or click the backdrop to close this dialog.</p>
</ui-dialog><script setup>
import { UiButton, UiDialog } from "@threadlabs/looma";
</script>
<template>
<UiButton
id="open-dismissible-dialog"
>Open dismissible dialog</UiButton>
<UiDialog
id="dismissible-dialog"
for="open-dismissible-dialog"
:modal="true"
closedby="any"
label="Keyboard shortcuts"
>
<p>Press <kbd>Escape</kbd> or click the backdrop to close this dialog.</p>
</UiDialog>
</template>import { UiButton, UiDialog } from "@threadlabs/looma";
export default function Example() {
return <>
<UiButton
id="open-dismissible-dialog"
>Open dismissible dialog</UiButton>
<UiDialog
id="dismissible-dialog"
htmlFor="open-dismissible-dialog"
modal
closedby="any"
label="Keyboard shortcuts"
>
<p>Press <kbd>Escape</kbd> or click the backdrop to close this dialog.</p>
</UiDialog>
</>;
}/** @jsxImportSource preact */
import { UiButton, UiDialog } from "@threadlabs/looma";
export default function Example() {
return <>
<UiButton
id="open-dismissible-dialog"
>Open dismissible dialog</UiButton>
<UiDialog
id="dismissible-dialog"
htmlFor="open-dismissible-dialog"
modal
closedby="any"
label="Keyboard shortcuts"
>
<p>Press <kbd>Escape</kbd> or click the backdrop to close this dialog.</p>
</UiDialog>
</>;
}<script>
import { UiButton, UiDialog } from "@threadlabs/looma";
</script>
<UiButton
id="open-dismissible-dialog"
>Open dismissible dialog</UiButton>
<UiDialog
id="dismissible-dialog"
for="open-dismissible-dialog"
modal
closedby="any"
label="Keyboard shortcuts"
>
<p>Press <kbd>Escape</kbd> or click the backdrop to close this dialog.</p>
</UiDialog>import { Component } from "@angular/core";
import { UiButton, UiDialog } from "@threadlabs/looma";
@Component({
selector: "example-view",
standalone: true,
imports: [UiButton, UiDialog],
template: `
<ng-template
ui-button
[hnAttributes]="{ id: 'open-dismissible-dialog' }"
>Open dismissible dialog</ng-template>
<dialog
ui-dialog
id="dismissible-dialog"
[for]="'open-dismissible-dialog'"
[modal]="true"
[closedby]="'any'"
[label]="'Keyboard shortcuts'"
>
<p>Press <kbd>Escape</kbd> or click the backdrop to close this dialog.</p>
</dialog>
`,
})
export default class Example {}Long content
The header and actions stay pinned while only the body scrolls, so the title, close button, and primary action are always reachable.
Code
<link
rel="component"
href="@threadlabs/looma/components/ui-button/ui-button.html"
>
<link
rel="component"
href="@threadlabs/looma/components/ui-dialog/ui-dialog.html"
>
<ui-button
id="open-long-dialog"
>Open long dialog</ui-button>
<ui-dialog
id="long-dialog"
for="open-long-dialog"
modal
closedby="any"
label="Terms of service"
>
<p>Section 1. These terms describe how the service may be used, what data is stored, and how either party can end the agreement.</p>
<p>Section 2. These terms describe how the service may be used, what data is stored, and how either party can end the agreement.</p>
<p>Section 3. These terms describe how the service may be used, what data is stored, and how either party can end the agreement.</p>
<p>Section 4. These terms describe how the service may be used, what data is stored, and how either party can end the agreement.</p>
<p>Section 5. These terms describe how the service may be used, what data is stored, and how either party can end the agreement.</p>
<p>Section 6. These terms describe how the service may be used, what data is stored, and how either party can end the agreement.</p>
<p>Section 7. These terms describe how the service may be used, what data is stored, and how either party can end the agreement.</p>
<p>Section 8. These terms describe how the service may be used, what data is stored, and how either party can end the agreement.</p>
<p>Section 9. These terms describe how the service may be used, what data is stored, and how either party can end the agreement.</p>
<p>Section 10. These terms describe how the service may be used, what data is stored, and how either party can end the agreement.</p>
<p>Section 11. These terms describe how the service may be used, what data is stored, and how either party can end the agreement.</p>
<p>Section 12. These terms describe how the service may be used, what data is stored, and how either party can end the agreement.</p>
<p>Section 13. These terms describe how the service may be used, what data is stored, and how either party can end the agreement.</p>
<p>Section 14. These terms describe how the service may be used, what data is stored, and how either party can end the agreement.</p>
<p>Section 15. These terms describe how the service may be used, what data is stored, and how either party can end the agreement.</p>
<p>Section 16. These terms describe how the service may be used, what data is stored, and how either party can end the agreement.</p>
<ui-button
slot="actions"
commandfor="long-dialog"
command="close"
>Decline</ui-button>
<ui-button
slot="actions"
variant="solid"
commandfor="long-dialog"
command="close"
>Accept</ui-button>
</ui-dialog><script setup>
import { UiButton, UiDialog } from "@threadlabs/looma";
</script>
<template>
<UiButton
id="open-long-dialog"
>Open long dialog</UiButton>
<UiDialog
id="long-dialog"
for="open-long-dialog"
:modal="true"
closedby="any"
label="Terms of service"
>
<p>Section 1. These terms describe how the service may be used, what data is stored, and how either party can end the agreement.</p>
<p>Section 2. These terms describe how the service may be used, what data is stored, and how either party can end the agreement.</p>
<p>Section 3. These terms describe how the service may be used, what data is stored, and how either party can end the agreement.</p>
<p>Section 4. These terms describe how the service may be used, what data is stored, and how either party can end the agreement.</p>
<p>Section 5. These terms describe how the service may be used, what data is stored, and how either party can end the agreement.</p>
<p>Section 6. These terms describe how the service may be used, what data is stored, and how either party can end the agreement.</p>
<p>Section 7. These terms describe how the service may be used, what data is stored, and how either party can end the agreement.</p>
<p>Section 8. These terms describe how the service may be used, what data is stored, and how either party can end the agreement.</p>
<p>Section 9. These terms describe how the service may be used, what data is stored, and how either party can end the agreement.</p>
<p>Section 10. These terms describe how the service may be used, what data is stored, and how either party can end the agreement.</p>
<p>Section 11. These terms describe how the service may be used, what data is stored, and how either party can end the agreement.</p>
<p>Section 12. These terms describe how the service may be used, what data is stored, and how either party can end the agreement.</p>
<p>Section 13. These terms describe how the service may be used, what data is stored, and how either party can end the agreement.</p>
<p>Section 14. These terms describe how the service may be used, what data is stored, and how either party can end the agreement.</p>
<p>Section 15. These terms describe how the service may be used, what data is stored, and how either party can end the agreement.</p>
<p>Section 16. These terms describe how the service may be used, what data is stored, and how either party can end the agreement.</p>
<template #actions>
<UiButton
commandfor="long-dialog"
command="close"
>Decline</UiButton>
<UiButton
variant="solid"
commandfor="long-dialog"
command="close"
>Accept</UiButton>
</template>
</UiDialog>
</template>import { UiButton, UiDialog } from "@threadlabs/looma";
export default function Example() {
return <>
<UiButton
id="open-long-dialog"
>Open long dialog</UiButton>
<UiDialog
id="long-dialog"
htmlFor="open-long-dialog"
modal
closedby="any"
label="Terms of service"
slots={{
actions: <>
<UiButton
commandfor="long-dialog"
command="close"
>Decline</UiButton>
<UiButton
variant="solid"
commandfor="long-dialog"
command="close"
>Accept</UiButton>
</>,
}}
>
<p>Section 1. These terms describe how the service may be used, what data is stored, and how either party can end the agreement.</p>
<p>Section 2. These terms describe how the service may be used, what data is stored, and how either party can end the agreement.</p>
<p>Section 3. These terms describe how the service may be used, what data is stored, and how either party can end the agreement.</p>
<p>Section 4. These terms describe how the service may be used, what data is stored, and how either party can end the agreement.</p>
<p>Section 5. These terms describe how the service may be used, what data is stored, and how either party can end the agreement.</p>
<p>Section 6. These terms describe how the service may be used, what data is stored, and how either party can end the agreement.</p>
<p>Section 7. These terms describe how the service may be used, what data is stored, and how either party can end the agreement.</p>
<p>Section 8. These terms describe how the service may be used, what data is stored, and how either party can end the agreement.</p>
<p>Section 9. These terms describe how the service may be used, what data is stored, and how either party can end the agreement.</p>
<p>Section 10. These terms describe how the service may be used, what data is stored, and how either party can end the agreement.</p>
<p>Section 11. These terms describe how the service may be used, what data is stored, and how either party can end the agreement.</p>
<p>Section 12. These terms describe how the service may be used, what data is stored, and how either party can end the agreement.</p>
<p>Section 13. These terms describe how the service may be used, what data is stored, and how either party can end the agreement.</p>
<p>Section 14. These terms describe how the service may be used, what data is stored, and how either party can end the agreement.</p>
<p>Section 15. These terms describe how the service may be used, what data is stored, and how either party can end the agreement.</p>
<p>Section 16. These terms describe how the service may be used, what data is stored, and how either party can end the agreement.</p>
</UiDialog>
</>;
}/** @jsxImportSource preact */
import { UiButton, UiDialog } from "@threadlabs/looma";
export default function Example() {
return <>
<UiButton
id="open-long-dialog"
>Open long dialog</UiButton>
<UiDialog
id="long-dialog"
htmlFor="open-long-dialog"
modal
closedby="any"
label="Terms of service"
slots={{
actions: <>
<UiButton
commandfor="long-dialog"
command="close"
>Decline</UiButton>
<UiButton
variant="solid"
commandfor="long-dialog"
command="close"
>Accept</UiButton>
</>,
}}
>
<p>Section 1. These terms describe how the service may be used, what data is stored, and how either party can end the agreement.</p>
<p>Section 2. These terms describe how the service may be used, what data is stored, and how either party can end the agreement.</p>
<p>Section 3. These terms describe how the service may be used, what data is stored, and how either party can end the agreement.</p>
<p>Section 4. These terms describe how the service may be used, what data is stored, and how either party can end the agreement.</p>
<p>Section 5. These terms describe how the service may be used, what data is stored, and how either party can end the agreement.</p>
<p>Section 6. These terms describe how the service may be used, what data is stored, and how either party can end the agreement.</p>
<p>Section 7. These terms describe how the service may be used, what data is stored, and how either party can end the agreement.</p>
<p>Section 8. These terms describe how the service may be used, what data is stored, and how either party can end the agreement.</p>
<p>Section 9. These terms describe how the service may be used, what data is stored, and how either party can end the agreement.</p>
<p>Section 10. These terms describe how the service may be used, what data is stored, and how either party can end the agreement.</p>
<p>Section 11. These terms describe how the service may be used, what data is stored, and how either party can end the agreement.</p>
<p>Section 12. These terms describe how the service may be used, what data is stored, and how either party can end the agreement.</p>
<p>Section 13. These terms describe how the service may be used, what data is stored, and how either party can end the agreement.</p>
<p>Section 14. These terms describe how the service may be used, what data is stored, and how either party can end the agreement.</p>
<p>Section 15. These terms describe how the service may be used, what data is stored, and how either party can end the agreement.</p>
<p>Section 16. These terms describe how the service may be used, what data is stored, and how either party can end the agreement.</p>
</UiDialog>
</>;
}<script>
import { UiButton, UiDialog } from "@threadlabs/looma";
</script>
{#snippet actions()}
<UiButton
commandfor="long-dialog"
command="close"
>Decline</UiButton>
<UiButton
variant="solid"
commandfor="long-dialog"
command="close"
>Accept</UiButton>
{/snippet}
<UiButton
id="open-long-dialog"
>Open long dialog</UiButton>
<UiDialog
id="long-dialog"
for="open-long-dialog"
modal
closedby="any"
label="Terms of service"
slots={{ actions }}
>
<p>Section 1. These terms describe how the service may be used, what data is stored, and how either party can end the agreement.</p>
<p>Section 2. These terms describe how the service may be used, what data is stored, and how either party can end the agreement.</p>
<p>Section 3. These terms describe how the service may be used, what data is stored, and how either party can end the agreement.</p>
<p>Section 4. These terms describe how the service may be used, what data is stored, and how either party can end the agreement.</p>
<p>Section 5. These terms describe how the service may be used, what data is stored, and how either party can end the agreement.</p>
<p>Section 6. These terms describe how the service may be used, what data is stored, and how either party can end the agreement.</p>
<p>Section 7. These terms describe how the service may be used, what data is stored, and how either party can end the agreement.</p>
<p>Section 8. These terms describe how the service may be used, what data is stored, and how either party can end the agreement.</p>
<p>Section 9. These terms describe how the service may be used, what data is stored, and how either party can end the agreement.</p>
<p>Section 10. These terms describe how the service may be used, what data is stored, and how either party can end the agreement.</p>
<p>Section 11. These terms describe how the service may be used, what data is stored, and how either party can end the agreement.</p>
<p>Section 12. These terms describe how the service may be used, what data is stored, and how either party can end the agreement.</p>
<p>Section 13. These terms describe how the service may be used, what data is stored, and how either party can end the agreement.</p>
<p>Section 14. These terms describe how the service may be used, what data is stored, and how either party can end the agreement.</p>
<p>Section 15. These terms describe how the service may be used, what data is stored, and how either party can end the agreement.</p>
<p>Section 16. These terms describe how the service may be used, what data is stored, and how either party can end the agreement.</p>
</UiDialog>import { Component } from "@angular/core";
import { UiButton, UiDialog } from "@threadlabs/looma";
@Component({
selector: "example-view",
standalone: true,
imports: [UiButton, UiDialog],
template: `
<ng-template
ui-button
[hnAttributes]="{ id: 'open-long-dialog' }"
>Open long dialog</ng-template>
<dialog
ui-dialog
id="long-dialog"
[for]="'open-long-dialog'"
[modal]="true"
[closedby]="'any'"
[label]="'Terms of service'"
>
<p>Section 1. These terms describe how the service may be used, what data is stored, and how either party can end the agreement.</p>
<p>Section 2. These terms describe how the service may be used, what data is stored, and how either party can end the agreement.</p>
<p>Section 3. These terms describe how the service may be used, what data is stored, and how either party can end the agreement.</p>
<p>Section 4. These terms describe how the service may be used, what data is stored, and how either party can end the agreement.</p>
<p>Section 5. These terms describe how the service may be used, what data is stored, and how either party can end the agreement.</p>
<p>Section 6. These terms describe how the service may be used, what data is stored, and how either party can end the agreement.</p>
<p>Section 7. These terms describe how the service may be used, what data is stored, and how either party can end the agreement.</p>
<p>Section 8. These terms describe how the service may be used, what data is stored, and how either party can end the agreement.</p>
<p>Section 9. These terms describe how the service may be used, what data is stored, and how either party can end the agreement.</p>
<p>Section 10. These terms describe how the service may be used, what data is stored, and how either party can end the agreement.</p>
<p>Section 11. These terms describe how the service may be used, what data is stored, and how either party can end the agreement.</p>
<p>Section 12. These terms describe how the service may be used, what data is stored, and how either party can end the agreement.</p>
<p>Section 13. These terms describe how the service may be used, what data is stored, and how either party can end the agreement.</p>
<p>Section 14. These terms describe how the service may be used, what data is stored, and how either party can end the agreement.</p>
<p>Section 15. These terms describe how the service may be used, what data is stored, and how either party can end the agreement.</p>
<p>Section 16. These terms describe how the service may be used, what data is stored, and how either party can end the agreement.</p>
<ng-container ngProjectAs="[slot='actions']">
<ng-template
ui-button
[hnAttributes]="{ commandfor: 'long-dialog', command: 'close' }"
>Decline</ng-template>
<ng-template
ui-button
[variant]="'solid'"
[hnAttributes]="{ commandfor: 'long-dialog', command: 'close' }"
>Accept</ng-template>
</ng-container>
</dialog>
`,
})
export default class Example {}Alert confirmation
Alert dialogs are always modal, have no header close button, and cannot close from outside. Keep an explicit, focused action available.
Code
<link
rel="component"
href="@threadlabs/looma/components/ui-button/ui-button.html"
>
<link
rel="component"
href="@threadlabs/looma/components/ui-dialog/ui-dialog.html"
>
<ui-button
id="open-alert-dialog"
>Delete item</ui-button>
<ui-dialog
id="alert-dialog"
for="open-alert-dialog"
alert
closedby="none"
label="Delete item?"
>
<p
id="alert-description"
>This action cannot be undone.</p>
<ui-button
slot="actions"
commandfor="alert-dialog"
command="close"
autofocus
>Cancel</ui-button>
<ui-button
slot="actions"
variant="danger"
commandfor="alert-dialog"
command="close"
>Delete</ui-button>
</ui-dialog><script setup>
import { UiButton, UiDialog } from "@threadlabs/looma";
</script>
<template>
<UiButton
id="open-alert-dialog"
>Delete item</UiButton>
<UiDialog
id="alert-dialog"
for="open-alert-dialog"
:alert="true"
closedby="none"
label="Delete item?"
>
<p
id="alert-description"
>This action cannot be undone.</p>
<template #actions>
<UiButton
commandfor="alert-dialog"
command="close"
:autofocus="true"
>Cancel</UiButton>
<UiButton
variant="danger"
commandfor="alert-dialog"
command="close"
>Delete</UiButton>
</template>
</UiDialog>
</template>import { UiButton, UiDialog } from "@threadlabs/looma";
export default function Example() {
return <>
<UiButton
id="open-alert-dialog"
>Delete item</UiButton>
<UiDialog
id="alert-dialog"
htmlFor="open-alert-dialog"
alert
closedby="none"
label="Delete item?"
slots={{
actions: <>
<UiButton
commandfor="alert-dialog"
command="close"
autoFocus
>Cancel</UiButton>
<UiButton
variant="danger"
commandfor="alert-dialog"
command="close"
>Delete</UiButton>
</>,
}}
>
<p
id="alert-description"
>This action cannot be undone.</p>
</UiDialog>
</>;
}/** @jsxImportSource preact */
import { UiButton, UiDialog } from "@threadlabs/looma";
export default function Example() {
return <>
<UiButton
id="open-alert-dialog"
>Delete item</UiButton>
<UiDialog
id="alert-dialog"
htmlFor="open-alert-dialog"
alert
closedby="none"
label="Delete item?"
slots={{
actions: <>
<UiButton
commandfor="alert-dialog"
command="close"
autoFocus
>Cancel</UiButton>
<UiButton
variant="danger"
commandfor="alert-dialog"
command="close"
>Delete</UiButton>
</>,
}}
>
<p
id="alert-description"
>This action cannot be undone.</p>
</UiDialog>
</>;
}<script>
import { UiButton, UiDialog } from "@threadlabs/looma";
</script>
{#snippet actions()}
<UiButton
commandfor="alert-dialog"
command="close"
autofocus
>Cancel</UiButton>
<UiButton
variant="danger"
commandfor="alert-dialog"
command="close"
>Delete</UiButton>
{/snippet}
<UiButton
id="open-alert-dialog"
>Delete item</UiButton>
<UiDialog
id="alert-dialog"
for="open-alert-dialog"
alert
closedby="none"
label="Delete item?"
slots={{ actions }}
>
<p
id="alert-description"
>This action cannot be undone.</p>
</UiDialog>import { Component } from "@angular/core";
import { UiButton, UiDialog } from "@threadlabs/looma";
@Component({
selector: "example-view",
standalone: true,
imports: [UiButton, UiDialog],
template: `
<ng-template
ui-button
[hnAttributes]="{ id: 'open-alert-dialog' }"
>Delete item</ng-template>
<dialog
ui-dialog
id="alert-dialog"
[for]="'open-alert-dialog'"
[alert]="true"
[closedby]="'none'"
[label]="'Delete item?'"
>
<p
id="alert-description"
>This action cannot be undone.</p>
<ng-container ngProjectAs="[slot='actions']">
<ng-template
ui-button
[hnAttributes]="{ commandfor: 'alert-dialog', command: 'close', autofocus: true }"
>Cancel</ng-template>
<ng-template
ui-button
[variant]="'danger'"
[hnAttributes]="{ commandfor: 'alert-dialog', command: 'close' }"
>Delete</ng-template>
</ng-container>
</dialog>
`,
})
export default class Example {}Sizes
Choose a common width with size. Glassiness and surface separation follow the shared theme; dialog purpose and rendered size determine the material treatment automatically. This dialog is non-modal, so the rest of the page remains interactive.
Code
<link
rel="component"
href="@threadlabs/looma/components/ui-button/ui-button.html"
>
<link
rel="component"
href="@threadlabs/looma/components/ui-dialog/ui-dialog.html"
>
<ui-button
id="open-wide-dialog"
>Open wide dialog</ui-button>
<ui-dialog
id="wide-dialog"
for="open-wide-dialog"
size="lg"
label="Reference details"
>
<p>Keep the rest of the page available while reviewing these details.</p>
<ui-button
slot="actions"
commandfor="wide-dialog"
command="close"
>Done</ui-button>
</ui-dialog><script setup>
import { UiButton, UiDialog } from "@threadlabs/looma";
</script>
<template>
<UiButton
id="open-wide-dialog"
>Open wide dialog</UiButton>
<UiDialog
id="wide-dialog"
for="open-wide-dialog"
size="lg"
label="Reference details"
>
<p>Keep the rest of the page available while reviewing these details.</p>
<template #actions>
<UiButton
commandfor="wide-dialog"
command="close"
>Done</UiButton>
</template>
</UiDialog>
</template>import { UiButton, UiDialog } from "@threadlabs/looma";
export default function Example() {
return <>
<UiButton
id="open-wide-dialog"
>Open wide dialog</UiButton>
<UiDialog
id="wide-dialog"
htmlFor="open-wide-dialog"
size="lg"
label="Reference details"
slots={{
actions: <UiButton
commandfor="wide-dialog"
command="close"
>Done</UiButton>,
}}
>
<p>Keep the rest of the page available while reviewing these details.</p>
</UiDialog>
</>;
}/** @jsxImportSource preact */
import { UiButton, UiDialog } from "@threadlabs/looma";
export default function Example() {
return <>
<UiButton
id="open-wide-dialog"
>Open wide dialog</UiButton>
<UiDialog
id="wide-dialog"
htmlFor="open-wide-dialog"
size="lg"
label="Reference details"
slots={{
actions: <UiButton
commandfor="wide-dialog"
command="close"
>Done</UiButton>,
}}
>
<p>Keep the rest of the page available while reviewing these details.</p>
</UiDialog>
</>;
}<script>
import { UiButton, UiDialog } from "@threadlabs/looma";
</script>
{#snippet actions()}
<UiButton
commandfor="wide-dialog"
command="close"
>Done</UiButton>
{/snippet}
<UiButton
id="open-wide-dialog"
>Open wide dialog</UiButton>
<UiDialog
id="wide-dialog"
for="open-wide-dialog"
size="lg"
label="Reference details"
slots={{ actions }}
>
<p>Keep the rest of the page available while reviewing these details.</p>
</UiDialog>import { Component } from "@angular/core";
import { UiButton, UiDialog } from "@threadlabs/looma";
@Component({
selector: "example-view",
standalone: true,
imports: [UiButton, UiDialog],
template: `
<ng-template
ui-button
[hnAttributes]="{ id: 'open-wide-dialog' }"
>Open wide dialog</ng-template>
<dialog
ui-dialog
id="wide-dialog"
[for]="'open-wide-dialog'"
[size]="'lg'"
[label]="'Reference details'"
>
<p>Keep the rest of the page available while reviewing these details.</p>
<ng-container ngProjectAs="[slot='actions']">
<ng-template
ui-button
[hnAttributes]="{ commandfor: 'wide-dialog', command: 'close' }"
>Done</ng-template>
</ng-container>
</dialog>
`,
})
export default class Example {}API
Package: @threadlabs/looma · Native root: dialog
Attributes
| Name | Description | Property | Type | Default | Allowed values |
|---|---|---|---|---|---|
alert | Use alert dialog semantics and require an explicit action instead of the header close button. An alert dialog is always modal. | alert | boolean | false | — |
closedby | Which user close requests work: any includes outside presses, closerequest includes Escape, and none requires an action. Unset follows native dialog: closerequest when modal, none when not. | closedby | keyword | — | any, closerequest, none |
for | ID of the control that opens the dialog. | for | string | | — |
label | Visible title in the dialog header; also its accessible name. | label | string | — | — |
modal | Open in the top layer with a backdrop and make the rest of the page inert until it closes, like native showModal(). Without it the dialog is non-modal, like native show(). | modal | boolean | false | — |
modeless | Deprecated: does nothing, since dialogs are non-modal unless modal is set. Accepted so markup written for 0.15 keeps working; modal wins when both are set. | modeless | boolean | false | — |
open | Whether the dialog is open initially or when set externally. | open | boolean | false | — |
size | Choose a compact, standard, wide, or viewport-filling dialog. Shared surface separation adapts to dialog purpose and rendered size. | size | keyword | md | sm, md, lg, fullscreen |
Framework props
| Name | Type | Default | Allowed values |
|---|---|---|---|
alert | boolean | false | — |
closedby | "any" | "closerequest" | "none" | — | any, closerequest, none |
for | string | | — |
label | string | — | — |
modal | boolean | false | — |
modeless | boolean | false | — |
open | boolean | false | — |
size | "sm" | "md" | "lg" | "fullscreen" | md | sm, md, lg, fullscreen |
Events
| Name | Detail | Description |
|---|---|---|
close | object
| Emitted when the component transitions to a closed state. |
open | object
| Emitted when the component transitions to an open state. |
Slots
| Name | Purpose |
|---|---|
default | Default child content. |
actions | Named content for the actions region. |
Design tokens
Set shared theme properties on a theme boundary. Component hooks apply only to their owning component.
Component tokens
| Token | Declared values | Fallback |
|---|---|---|
--ui-dialog-border | — | var(--ui-overlay-border, var(--ui-border-strong)) | color-mix(in oklab, var(--ui-overlay-border, var(--ui-border-strong)) calc((1 - var(--_ui-material-active)) * 100%), transparent) |
--ui-dialog-duration | — | var(--ui-motion-base) |
--ui-dialog-max-width | — | var(--_ui-dialog-size, 440px) |
--ui-dialog-radius | — | var(--ui-overlay-radius, var(--ui-radius-dialog)) | 0 |
--ui-dialog-shadow | — | var(--ui-overlay-shadow, var(--ui-elevation-dialog, var(--ui-shadow-xl))) | var(
--ui-overlay-shadow,
0 calc(var(--_ui-material-separation) * var(--_ui-material-scale, 1) * 8px) calc(
var(--_ui-material-separation) * var(--_ui-material-scale, 1) * 24px
) color-mix(in oklab, var(--ui-text-primary) 15%, transparent),
var(--ui-material-glow, 0 0 transparent),
inset 0 0 0 calc(var(--_ui-material-active) * var(--ui-border-width)) var(--ui-material-edge, var(--ui-border-strong)),
var(--ui-elevation-dialog, var(--ui-shadow-xl))
) |
--ui-dialog-surface | — | var(--ui-overlay-surface, var(--ui-surface-elevated)) | var(--_ui-material-underpaint, var(--ui-material-content, var(--ui-overlay-surface, var(--ui-surface-elevated)))) |
--ui-dialog-viewport-gap | — | var(--ui-space-4) |
Shared tokens
| Token | Fallback |
|---|---|
--ui-border-strong | — |
--ui-border-width | — |
--ui-elevation-dialog | var(--ui-shadow-xl) |
--ui-font-semibold | — |
--ui-font-size-lg | — |
--ui-glassiness | 0 |
--ui-line-height-tight | — |
--ui-material-content | var(--ui-overlay-surface, var(--ui-surface-elevated)) |
--ui-material-edge | var(--ui-border-strong) |
--ui-material-glass | var(--ui-surface-elevated) |
--ui-material-glow | 0 0 transparent |
--ui-material-highlight | var(--ui-surface-highlight, linear-gradient(transparent, transparent)) |
--ui-motion-base | — |
--ui-motion-ease | — |
--ui-overlay-backdrop | — |
--ui-overlay-border | var(--ui-border-strong) |
--ui-overlay-radius | var(--ui-radius-dialog) |
--ui-overlay-shadow | var(--ui-elevation-dialog, var(--ui-shadow-xl)) | 0 calc(var(--_ui-material-separation) * var(--_ui-material-scale, 1) * 8px) calc(
var(--_ui-material-separation) * var(--_ui-material-scale, 1) * 24px
) color-mix(in oklab, var(--ui-text-primary) 15%, transparent),
var(--ui-material-glow, 0 0 transparent),
inset 0 0 0 calc(var(--_ui-material-active) * var(--ui-border-width)) var(--ui-material-edge, var(--ui-border-strong)),
var(--ui-elevation-dialog, var(--ui-shadow-xl)) |
--ui-overlay-surface | var(--ui-surface-elevated) |
--ui-radius-dialog | — |
--ui-shadow-xl | — |
--ui-space-1 | — |
--ui-space-2 | — |
--ui-space-3 | — |
--ui-space-4 | — |
--ui-space-5 | — |
--ui-surface-elevated | — |
--ui-surface-highlight | linear-gradient(transparent, transparent) |
--ui-surface-separation | 0 |
--ui-text-primary | — |