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

NameDescriptionPropertyTypeDefaultAllowed values
durationDefault milliseconds for toasts added with the show-toast event or command; 0 keeps each until dismissed. Hover or focus pauses a timer.durationnumber0—
placementScreen edge where the stack appears. Start and end follow the writing direction.placementkeywordtoptop, top-start, top-end, bottom, bottom-start, bottom-end

Framework props

NameTypeDefaultAllowed values
durationnumber0—
placement"top" | "top-start" | "top-end" | "bottom" | "bottom-start" | "bottom-end"toptop, top-start, top-end, bottom, bottom-start, bottom-end

Events

NameDetailDescription
dismissobject
  • id: string (required)
  • reason: keyword (required)
  • trigger: keyword (required)
Emitted when a toast item is dismissed from its region.
show-toastobject
  • message: string (required)
  • id: string
  • tone: keyword
  • duration: number
Dispatch on the region to add a message; an optional id identifies its later dismiss event.

Slots

NamePurpose
defaultDefault child content.

Design tokens

Set shared theme properties on a theme boundary. Component hooks apply only to their owning component.

Component tokens

TokenDeclared valuesFallback
--ui-overlay-bordervar(--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-surfacevar(--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

TokenFallback
--ui-border-strong—
--ui-border-width—
--ui-danger-soft—
--ui-danger-soft-border—
--ui-danger-subtle-text—
--ui-elevation-overlayvar(--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-outcubic-bezier(0.16, 1, 0.3, 1)
--ui-overlay-radiusvar(--ui-radius-lg)
--ui-overlay-shadowvar(--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

NameDescriptionPropertyTypeDefaultAllowed values
durationMilliseconds 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.durationnumber0—
toneSemantic accent for this message. Danger uses an assertive alert role; the other tones use polite status semantics.tonekeywordneutralneutral, info, success, warning, danger

Framework props

NameTypeDefaultAllowed values
durationnumber0—
tone"neutral" | "info" | "success" | "warning" | "danger"neutralneutral, info, success, warning, danger

Events

NameDetailDescription
dismissobject
  • id: string (required)
  • reason: keyword (required)
  • trigger: keyword (required)
Emitted when a toast item is dismissed from its region.

Slots

NamePurpose
defaultDefault child content.
actionNamed 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

TokenDeclared valuesFallback
--ui-overlay-surfacevar(--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-accentvar(--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

TokenFallback
--ui-border-strong—
--ui-border-width—
--ui-danger-soft—
--ui-danger-soft-border—
--ui-danger-subtle-text—
--ui-elevation-overlayvar(--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-bordervar(--ui-border-strong) | var(--ui-toast-accent, var(--_ui-toast-accent))
--ui-overlay-radiusvar(--ui-radius-lg)
--ui-overlay-shadowvar(--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—