Skip to content

Announce transient status from an explicit toaster. Custom element

Toast
Copy this markup
<ui-toaster role="region" aria-label="Notifications" placement="bottom-end" stack="overlap">
<ui-toast role="status">
<div data-ui-part="content">
<h2 data-ui-part="title">Preview ready</h2>
<p data-ui-part="description">The static example finished building.</p>
</div>
<button data-ui-part="close" type="button" aria-label="Dismiss notification">
<svg aria-hidden="true" focusable="false" viewBox="0 0 16 16">
<path d="m4.5 4.5 7 7m0-7-7 7" fill="none" stroke="currentColor" stroke-linecap="round" stroke-width="1"/>
</svg>
</button>
</ui-toast>
</ui-toaster>

Install

Styles and registration
import '@timelessui/components/css/tokens.css'
import '@timelessui/components/css/core/toast.css'
import '@timelessui/components/css/themes/atmosphere/tokens.css'
import '@timelessui/components/css/themes/atmosphere/toast.css'
import '@timelessui/components/register/ui-toaster'
import '@timelessui/components/register/ui-toast'

A register/ import is a side effect: it defines the element as the module evaluates, so it has to run in code the browser loads. To register explicitly instead — to control the timing, or to define into another window — call the function from the matching define/ entry point, which registers nothing on its own:

Explicit registration
import { defineToasterElement } from '@timelessui/components/define/ui-toaster'
defineToasterElement()
import { defineToastElement } from '@timelessui/components/define/ui-toast'
defineToastElement()

Anatomy

Parts are authored in your own markup and identified by the selector below, so your CSS can target the same anatomy without loading Timeless styles. Required parts must be present for the component to work. Private data-ui-internal-* hooks are written by the runtime and must never be authored.

<ui-toast>

PartRequiredSelectorPurpose
contentNo[data-ui-part~='content']Wrapper for the title and description.
titleNo[data-ui-part~='title']Short summary line.
descriptionNo[data-ui-part~='description']Supporting detail.
closeNo[data-ui-part~='close']Dismiss button. Give it an accessible name.

Attributes

Every value below is implemented by the stylesheets this component ships. Boolean attributes are presence-based: author the attribute with no value, or omit it.

<ui-toaster>

AttributeValuesDefaultDescription
placementtop-start · top-center · top-end · bottom-start · bottom-center · bottom-endbottom-endCorner or edge of the viewport the toasts stack against.
stackoverlap · listoverlapWhether queued toasts overlap into a deck (overlap) or lay out as a full list (list).

<ui-toast>

AttributeValuesDefaultDescription
durationany number5000Milliseconds before the toast dismisses itself. 0 keeps it open until dismissed.
persistentpresenceabsentPresent to disable auto-dismiss regardless of duration.

Element API

Attributes above are the authoring surface. These are the DOM properties and events the registered element adds once it upgrades.

<ui-toaster>

PropertyTypeNotes
placement'top-start' | 'top-center' | 'top-end' | 'bottom-start' | 'bottom-center' | 'bottom-end'Reflects the placement attribute, documented above.
stack'overlap' | 'list'Reflects the stack attribute, documented above.

This element dispatches no component events.

<ui-toast>

PropertyTypeNotes
durationstringReflects the duration attribute, documented above.
persistentbooleanReflects the persistent attribute, documented above.
EventDetailDescription
ui-dismissCustomEvent<ToastDismissDetail>Dispatched when the toast is dismissed. The detail names the reason: a timeout, the close control, or the imperative API.

Styling

Root identity: ui-toaster, ui-toast. Required stylesheets: tokens.css, core/toast.css, themes/atmosphere/tokens.css, themes/atmosphere/toast.css.

Set these custom properties to restyle the component:

Custom propertyControls
--ui-toaster-gapGap between toasts in list mode.
--ui-toaster-overlapOffset between stacked toasts in overlap mode.
Design tokens this component reads (13)

These are global Atmosphere tokens. Change them once at the theme level rather than per component.

--ui-bg-control · --ui-bg-surface · --ui-fg · --ui-fg-muted · --ui-focus · --ui-line · --ui-radius-lg · --ui-radius-md · --ui-shadow-floating · --ui-space-1 · --ui-space-3 · --ui-space-4 · --ui-space-5

Accessibility

Keep the native elements, roles, and relationships shown in the example. Timeless adds only the state and keyboard coordination the platform does not already provide, and it never supplies your accessible names — those depend on your content.

<ui-toaster>

Follows the Alert pattern from the ARIA Authoring Practices Guide.

The toaster is the live region, and it is yours to name — author role="region" with an aria-label, or role="status" when the whole surface should announce. Timeless supplies both as a default and neither as a replacement for your own. Nothing here traps focus or steals it: a toast appears without moving the user, and is reached with Tab like anything else. Choose the role by urgency, not by appearance: role="status" on a toast is polite and waits its turn, role="alert" interrupts and should be rare.

<ui-toast>

Follows the Alert pattern from the ARIA Authoring Practices Guide.

Give the toast the role its urgency deserves — role="status" for the ordinary case, role="alert" only when it must interrupt — and give the close control an accessible name. SC 2.2.1 is the criterion to hold in mind: duration defaults to 5000ms, and the timer stops while the toast is hovered or contains focus, so nobody loses the message they are reading or the control they are reaching for. persistent, or duration="0", removes the limit outright, which is the right choice for anything the user must act on. Dismissing a toast that holds focus hands focus to a surviving toast, or back to wherever it came from, rather than dropping it on <body>.

Before JavaScript runs

The markup above is complete and usable on its own: native controls submit, labels associate, and authored ARIA is already correct. Registration adds state synchronisation, focus management, and keyboard coordination on top of it.

More examples

Open Toast in StoryLite for variants, controls, and manual testing.