Toast Region
Toast Region stacks authored <ui-toast> children and messages added with the show-toast event or the --show-toast command.
Show a notification
The region appears when a command adds a message and hides again after its last toast is dismissed.
Code
<link
rel="component"
href="@threadlabs/looma/components/ui-toast-region/ui-toast-region.html"
>
<link
rel="component"
href="@threadlabs/looma/components/ui-button/ui-button.html"
>
<ui-toast-region
id="notifications"
> </ui-toast-region>
<ui-button
commandfor="notifications"
command="--show-toast"
value="Page saved."
>Show toast</ui-button><script setup>
import { UiButton, UiToastRegion } from "@threadlabs/looma";
</script>
<template>
<UiToastRegion
id="notifications"
> </UiToastRegion>
<UiButton
commandfor="notifications"
command="--show-toast"
value="Page saved."
>Show toast</UiButton>
</template>import { UiButton, UiToastRegion } from "@threadlabs/looma";
export default function Example() {
return <>
<UiToastRegion
id="notifications"
> </UiToastRegion>
<UiButton
commandfor="notifications"
command="--show-toast"
value="Page saved."
>Show toast</UiButton>
</>;
}/** @jsxImportSource preact */
import { UiButton, UiToastRegion } from "@threadlabs/looma";
export default function Example() {
return <>
<UiToastRegion
id="notifications"
> </UiToastRegion>
<UiButton
commandfor="notifications"
command="--show-toast"
value="Page saved."
>Show toast</UiButton>
</>;
}<script>
import { UiButton, UiToastRegion } from "@threadlabs/looma";
</script>
<UiToastRegion
id="notifications"
> </UiToastRegion>
<UiButton
commandfor="notifications"
command="--show-toast"
value="Page saved."
>Show toast</UiButton>import { Component } from "@angular/core";
import { UiButton, UiToastRegion } from "@threadlabs/looma";
@Component({
selector: "example-view",
standalone: true,
imports: [UiToastRegion, UiButton],
template: `
<div
ui-toast-region
id="notifications"
> </div>
<ng-template
ui-button
[hnAttributes]="{ commandfor: 'notifications', command: '--show-toast', value: 'Page saved.' }"
>Show toast</ng-template>
`,
})
export default class Example {}Multiple messages
The region stacks messages; each keeps its own round dismiss control.
Code
<link
rel="component"
href="@threadlabs/looma/components/ui-toast-region/ui-toast-region.html"
>
<link
rel="component"
href="@threadlabs/looma/components/ui-cluster/ui-cluster.html"
>
<link
rel="component"
href="@threadlabs/looma/components/ui-button/ui-button.html"
>
<ui-toast-region
id="multiple-notifications"
> </ui-toast-region>
<ui-cluster
gap="s"
>
<ui-button
commandfor="multiple-notifications"
command="--show-toast"
value="Page published."
>Show published</ui-button>
<ui-button
commandfor="multiple-notifications"
command="--show-toast"
value="Link copied."
>Show copied</ui-button>
</ui-cluster><script setup>
import { UiButton, UiCluster, UiToastRegion } from "@threadlabs/looma";
</script>
<template>
<UiToastRegion
id="multiple-notifications"
> </UiToastRegion>
<UiCluster
gap="s"
>
<UiButton
commandfor="multiple-notifications"
command="--show-toast"
value="Page published."
>Show published</UiButton>
<UiButton
commandfor="multiple-notifications"
command="--show-toast"
value="Link copied."
>Show copied</UiButton>
</UiCluster>
</template>import { UiButton, UiCluster, UiToastRegion } from "@threadlabs/looma";
export default function Example() {
return <>
<UiToastRegion
id="multiple-notifications"
> </UiToastRegion>
<UiCluster
gap="s"
>
<UiButton
commandfor="multiple-notifications"
command="--show-toast"
value="Page published."
>Show published</UiButton>
<UiButton
commandfor="multiple-notifications"
command="--show-toast"
value="Link copied."
>Show copied</UiButton>
</UiCluster>
</>;
}/** @jsxImportSource preact */
import { UiButton, UiCluster, UiToastRegion } from "@threadlabs/looma";
export default function Example() {
return <>
<UiToastRegion
id="multiple-notifications"
> </UiToastRegion>
<UiCluster
gap="s"
>
<UiButton
commandfor="multiple-notifications"
command="--show-toast"
value="Page published."
>Show published</UiButton>
<UiButton
commandfor="multiple-notifications"
command="--show-toast"
value="Link copied."
>Show copied</UiButton>
</UiCluster>
</>;
}<script>
import { UiButton, UiCluster, UiToastRegion } from "@threadlabs/looma";
</script>
<UiToastRegion
id="multiple-notifications"
> </UiToastRegion>
<UiCluster
gap="s"
>
<UiButton
commandfor="multiple-notifications"
command="--show-toast"
value="Page published."
>Show published</UiButton>
<UiButton
commandfor="multiple-notifications"
command="--show-toast"
value="Link copied."
>Show copied</UiButton>
</UiCluster>import { Component } from "@angular/core";
import { UiButton, UiCluster, UiToastRegion } from "@threadlabs/looma";
@Component({
selector: "example-view",
standalone: true,
imports: [UiToastRegion, UiCluster, UiButton],
template: `
<div
ui-toast-region
id="multiple-notifications"
> </div>
<div
ui-cluster
[gap]="'s'"
>
<ng-template
ui-button
[hnAttributes]="{ commandfor: 'multiple-notifications', command: '--show-toast', value: 'Page published.' }"
>Show published</ng-template>
<ng-template
ui-button
[hnAttributes]="{ commandfor: 'multiple-notifications', command: '--show-toast', value: 'Link copied.' }"
>Show copied</ng-template>
</div>
`,
})
export default class Example {}Timed notification
A positive duration dismisses each generated message automatically. Hovering or focusing a message pauses its timer.
Code
<link
rel="component"
href="@threadlabs/looma/components/ui-toast-region/ui-toast-region.html"
>
<link
rel="component"
href="@threadlabs/looma/components/ui-button/ui-button.html"
>
<ui-toast-region
id="auto-notifications"
duration="3000"
> </ui-toast-region>
<ui-button
commandfor="auto-notifications"
command="--show-toast"
value="Draft saved."
>Show auto-dismissing toast</ui-button><script setup>
import { UiButton, UiToastRegion } from "@threadlabs/looma";
</script>
<template>
<UiToastRegion
id="auto-notifications"
:duration="3000"
> </UiToastRegion>
<UiButton
commandfor="auto-notifications"
command="--show-toast"
value="Draft saved."
>Show auto-dismissing toast</UiButton>
</template>import { UiButton, UiToastRegion } from "@threadlabs/looma";
export default function Example() {
return <>
<UiToastRegion
id="auto-notifications"
duration={3000}
> </UiToastRegion>
<UiButton
commandfor="auto-notifications"
command="--show-toast"
value="Draft saved."
>Show auto-dismissing toast</UiButton>
</>;
}/** @jsxImportSource preact */
import { UiButton, UiToastRegion } from "@threadlabs/looma";
export default function Example() {
return <>
<UiToastRegion
id="auto-notifications"
duration={3000}
> </UiToastRegion>
<UiButton
commandfor="auto-notifications"
command="--show-toast"
value="Draft saved."
>Show auto-dismissing toast</UiButton>
</>;
}<script>
import { UiButton, UiToastRegion } from "@threadlabs/looma";
</script>
<UiToastRegion
id="auto-notifications"
duration={3000}
> </UiToastRegion>
<UiButton
commandfor="auto-notifications"
command="--show-toast"
value="Draft saved."
>Show auto-dismissing toast</UiButton>import { Component } from "@angular/core";
import { UiButton, UiToastRegion } from "@threadlabs/looma";
@Component({
selector: "example-view",
standalone: true,
imports: [UiToastRegion, UiButton],
template: `
<div
ui-toast-region
id="auto-notifications"
[duration]="3000"
> </div>
<ng-template
ui-button
[hnAttributes]="{ commandfor: 'auto-notifications', command: '--show-toast', value: 'Draft saved.' }"
>Show auto-dismissing toast</ng-template>
`,
})
export default class Example {}Authored status and action
A toast can carry a semantic tone and an authored action. It starts hidden here; the application clears hidden to show it and handles the action, and the toast hides itself when dismissed.
Code
<link
rel="component"
href="@threadlabs/looma/components/ui-button/ui-button.html"
>
<link
rel="component"
href="@threadlabs/looma/components/ui-toast-region/ui-toast-region.html"
>
<link
rel="component"
href="@threadlabs/looma/components/ui-toast/ui-toast.html"
>
<ui-button
id="show-saved-toast"
data-example-id="show-saved-toast"
>Show toast</ui-button>
<ui-toast-region
placement="top-end"
>
<ui-toast
id="saved-toast"
data-example-id="saved-toast"
tone="success"
hidden
>
Draft saved.
<button
slot="action"
type="button"
>Undo</button>
</ui-toast>
</ui-toast-region><script setup>
import { UiButton, UiToast, UiToastRegion } from "@threadlabs/looma";
</script>
<template>
<UiButton
id="show-saved-toast"
data-example-id="show-saved-toast"
>Show toast</UiButton>
<UiToastRegion
placement="top-end"
>
<UiToast
id="saved-toast"
data-example-id="saved-toast"
tone="success"
:hidden="true"
> Draft saved. <template #action>
<button
type="button"
>Undo</button>
</template> </UiToast>
</UiToastRegion>
</template>import { UiButton, UiToast, UiToastRegion } from "@threadlabs/looma";
export default function Example() {
return <>
<UiButton
id="show-saved-toast"
data-example-id="show-saved-toast"
>Show toast</UiButton>
<UiToastRegion
placement="top-end"
>
<UiToast
id="saved-toast"
data-example-id="saved-toast"
tone="success"
hidden
slots={{
action: <button
type="button"
>Undo</button>,
}}
>{" Draft saved. "}{" "}</UiToast>
</UiToastRegion>
</>;
}/** @jsxImportSource preact */
import { UiButton, UiToast, UiToastRegion } from "@threadlabs/looma";
export default function Example() {
return <>
<UiButton
id="show-saved-toast"
data-example-id="show-saved-toast"
>Show toast</UiButton>
<UiToastRegion
placement="top-end"
>
<UiToast
id="saved-toast"
data-example-id="saved-toast"
tone="success"
hidden
slots={{
action: <button
type="button"
>Undo</button>,
}}
>{" Draft saved. "}{" "}</UiToast>
</UiToastRegion>
</>;
}<script>
import { UiButton, UiToast, UiToastRegion } from "@threadlabs/looma";
</script>
{#snippet action()}
<button
type="button"
>Undo</button>
{/snippet}
<UiButton
id="show-saved-toast"
data-example-id="show-saved-toast"
>Show toast</UiButton>
<UiToastRegion
placement="top-end"
>
<UiToast
id="saved-toast"
data-example-id="saved-toast"
tone="success"
hidden
slots={{ action }}
> Draft saved. </UiToast>
</UiToastRegion>import { Component } from "@angular/core";
import { UiButton, UiToast, UiToastRegion } from "@threadlabs/looma";
@Component({
selector: "example-view",
standalone: true,
imports: [UiButton, UiToastRegion, UiToast],
template: `
<ng-template
ui-button
[hnAttributes]="{ id: 'show-saved-toast', 'data-example-id': 'show-saved-toast' }"
>Show toast</ng-template>
<div
ui-toast-region
[placement]="'top-end'"
>
<div
ui-toast
id="saved-toast"
data-example-id="saved-toast"
[tone]="'success'"
hidden
> Draft saved. <ng-container ngProjectAs="[slot='action']">
<button
type="button"
>Undo</button>
</ng-container> </div>
</div>
`,
})
export default class Example {}Danger alert
A danger toast uses an assertive alert role. Keep important alerts persistent until a person can act on them. Clearing hidden shows it, and it hides itself when dismissed.
Code
<link
rel="component"
href="@threadlabs/looma/components/ui-button/ui-button.html"
>
<link
rel="component"
href="@threadlabs/looma/components/ui-toast-region/ui-toast-region.html"
>
<link
rel="component"
href="@threadlabs/looma/components/ui-toast/ui-toast.html"
>
<ui-button
id="show-failed-toast"
data-example-id="show-failed-toast"
>Show alert</ui-button>
<ui-toast-region
placement="bottom"
>
<ui-toast
id="failed-toast"
data-example-id="failed-toast"
tone="danger"
hidden
>The upload failed. Check the connection and try again.</ui-toast>
</ui-toast-region><script setup>
import { UiButton, UiToast, UiToastRegion } from "@threadlabs/looma";
</script>
<template>
<UiButton
id="show-failed-toast"
data-example-id="show-failed-toast"
>Show alert</UiButton>
<UiToastRegion
placement="bottom"
>
<UiToast
id="failed-toast"
data-example-id="failed-toast"
tone="danger"
:hidden="true"
>The upload failed. Check the connection and try again.</UiToast>
</UiToastRegion>
</template>import { UiButton, UiToast, UiToastRegion } from "@threadlabs/looma";
export default function Example() {
return <>
<UiButton
id="show-failed-toast"
data-example-id="show-failed-toast"
>Show alert</UiButton>
<UiToastRegion
placement="bottom"
>
<UiToast
id="failed-toast"
data-example-id="failed-toast"
tone="danger"
hidden
>The upload failed. Check the connection and try again.</UiToast>
</UiToastRegion>
</>;
}/** @jsxImportSource preact */
import { UiButton, UiToast, UiToastRegion } from "@threadlabs/looma";
export default function Example() {
return <>
<UiButton
id="show-failed-toast"
data-example-id="show-failed-toast"
>Show alert</UiButton>
<UiToastRegion
placement="bottom"
>
<UiToast
id="failed-toast"
data-example-id="failed-toast"
tone="danger"
hidden
>The upload failed. Check the connection and try again.</UiToast>
</UiToastRegion>
</>;
}<script>
import { UiButton, UiToast, UiToastRegion } from "@threadlabs/looma";
</script>
<UiButton
id="show-failed-toast"
data-example-id="show-failed-toast"
>Show alert</UiButton>
<UiToastRegion
placement="bottom"
>
<UiToast
id="failed-toast"
data-example-id="failed-toast"
tone="danger"
hidden
>The upload failed. Check the connection and try again.</UiToast>
</UiToastRegion>import { Component } from "@angular/core";
import { UiButton, UiToast, UiToastRegion } from "@threadlabs/looma";
@Component({
selector: "example-view",
standalone: true,
imports: [UiButton, UiToastRegion, UiToast],
template: `
<ng-template
ui-button
[hnAttributes]="{ id: 'show-failed-toast', 'data-example-id': 'show-failed-toast' }"
>Show alert</ng-template>
<div
ui-toast-region
[placement]="'bottom'"
>
<div
ui-toast
id="failed-toast"
data-example-id="failed-toast"
[tone]="'danger'"
hidden
>The upload failed. Check the connection and try again.</div>
</div>
`,
})
export default class Example {}API
Package: @threadlabs/looma · Native root: div
Attributes
| Name | Description | Property | Type | Default | Allowed values |
|---|---|---|---|---|---|
duration | Default milliseconds for toasts added with the show-toast event or command; 0 keeps each until dismissed. Hover or focus pauses a timer. | duration | number | 0 | — |
placement | Screen edge where the stack appears. Start and end follow the writing direction. | placement | keyword | top | top, top-start, top-end, bottom, bottom-start, bottom-end |
Framework props
| Name | Type | Default | Allowed values |
|---|---|---|---|
duration | number | 0 | — |
placement | "top" | "top-start" | "top-end" | "bottom" | "bottom-start" | "bottom-end" | top | top, top-start, top-end, bottom, bottom-start, bottom-end |
Events
| Name | Detail | Description |
|---|---|---|
dismiss | object
| Emitted when a toast item is dismissed from its region. |
show-toast | object
| Dispatch on the region to add a message; an optional id identifies its later dismiss event. |
Slots
| Name | Purpose |
|---|---|
default | Default child content. |
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-overlay-border | var(--ui-overlay-border, var(--ui-border-strong)) | var(--ui-info-soft-border) | var(--ui-success-soft-border) | var(--ui-warning-soft-border) | var(--ui-danger-soft-border) | var(--ui-border-strong) |
--ui-overlay-surface | var(--ui-overlay-surface, var(--ui-surface-muted)) | var(--ui-info-soft) | var(--ui-success-soft) | var(--ui-warning-soft) | var(--ui-danger-soft) | var(--ui-surface-muted) |
--ui-toast-region-border | — | var(--ui-overlay-border, var(--_ui-toast-region-accent)) |
--ui-toast-region-enter-duration | — | 0.32s |
--ui-toast-region-exit-duration | — | 0.22s |
--ui-toast-region-radius | — | var(--ui-overlay-radius, var(--ui-radius-lg)) |
--ui-toast-region-shadow | — | var(--ui-overlay-shadow, var(--ui-elevation-overlay, var(--ui-shadow-lg))) |
--ui-toast-region-surface | — | var(--ui-overlay-surface, var(--_ui-toast-region-tone-surface)) |
Shared tokens
| Token | Fallback |
|---|---|
--ui-border-strong | — |
--ui-border-width | — |
--ui-danger-soft | — |
--ui-danger-soft-border | — |
--ui-danger-subtle-text | — |
--ui-elevation-overlay | var(--ui-shadow-lg) |
--ui-font-family-sans | — |
--ui-font-normal | — |
--ui-font-size-sm | — |
--ui-info-soft | — |
--ui-info-soft-border | — |
--ui-info-subtle-text | — |
--ui-line-height-md | — |
--ui-motion-ease | — |
--ui-motion-ease-out | cubic-bezier(0.16, 1, 0.3, 1) |
--ui-overlay-radius | var(--ui-radius-lg) |
--ui-overlay-shadow | var(--ui-elevation-overlay, var(--ui-shadow-lg)) |
--ui-radius-lg | — |
--ui-shadow-lg | — |
--ui-space-2 | — |
--ui-space-3 | — |
--ui-space-4 | — |
--ui-success-soft | — |
--ui-success-soft-border | — |
--ui-success-subtle-text | — |
--ui-surface-muted | — |
--ui-text-primary | — |
--ui-warning-soft | — |
--ui-warning-soft-border | — |
--ui-warning-subtle-text | — |
Toast API
Author a toast inside Toast Region when its message has a tone, rich content, or an action.
Package: @threadlabs/looma · Native root: div
Attributes
| Name | Description | Property | Type | Default | Allowed values |
|---|---|---|---|---|---|
duration | Milliseconds the toast is shown before it dismisses itself; 0 keeps it until an action dismisses it. The timer starts when the toast is shown, starts again each time it is shown, and pauses on hover or focus. | duration | number | 0 | — |
tone | Semantic accent for this message. Danger uses an assertive alert role; the other tones use polite status semantics. | tone | keyword | neutral | neutral, info, success, warning, danger |
Framework props
| Name | Type | Default | Allowed values |
|---|---|---|---|
duration | number | 0 | — |
tone | "neutral" | "info" | "success" | "warning" | "danger" | neutral | neutral, info, success, warning, danger |
Events
| Name | Detail | Description |
|---|---|---|
dismiss | object
| Emitted when a toast item is dismissed from its region. |
Slots
| Name | Purpose |
|---|---|
default | Default child content. |
action | Named content for the action 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-overlay-surface | var(--ui-overlay-surface, var(--ui-surface-muted)) | var(--ui-info-soft) | var(--ui-success-soft) | var(--ui-warning-soft) | var(--ui-danger-soft) | var(--ui-surface-muted) |
--ui-toast-accent | var(--ui-overlay-border, var(--ui-border-strong)) | var(--ui-info-soft-border) | var(--ui-success-soft-border) | var(--ui-warning-soft-border) | var(--ui-danger-soft-border) | — |
--ui-toast-border | — | var(--ui-overlay-border, var(--ui-toast-accent, var(--_ui-toast-accent))) |
--ui-toast-radius | — | var(--ui-overlay-radius, var(--ui-radius-lg)) |
--ui-toast-shadow | — | var(--ui-overlay-shadow, var(--ui-elevation-overlay, var(--ui-shadow-lg))) |
--ui-toast-surface | — | var(--ui-overlay-surface, var(--_ui-toast-surface)) |
Shared tokens
| Token | Fallback |
|---|---|
--ui-border-strong | — |
--ui-border-width | — |
--ui-danger-soft | — |
--ui-danger-soft-border | — |
--ui-danger-subtle-text | — |
--ui-elevation-overlay | var(--ui-shadow-lg) |
--ui-font-family-sans | — |
--ui-font-normal | — |
--ui-font-size-sm | — |
--ui-info-soft | — |
--ui-info-soft-border | — |
--ui-info-subtle-text | — |
--ui-line-height-md | — |
--ui-overlay-border | var(--ui-border-strong) | var(--ui-toast-accent, var(--_ui-toast-accent)) |
--ui-overlay-radius | var(--ui-radius-lg) |
--ui-overlay-shadow | var(--ui-elevation-overlay, var(--ui-shadow-lg)) |
--ui-radius-lg | — |
--ui-shadow-lg | — |
--ui-space-2 | — |
--ui-space-3 | — |
--ui-space-4 | — |
--ui-success-soft | — |
--ui-success-soft-border | — |
--ui-success-subtle-text | — |
--ui-surface-muted | — |
--ui-text-primary | — |
--ui-warning-soft | — |
--ui-warning-soft-border | — |
--ui-warning-subtle-text | — |