Skip to content
Home Theme Gallery

Toast

The custom element is <hui-toast>.

Overview

A fixed live-region container that the host appends messages to, owning only politeness and timing. It auto-dismisses, pausing while hovered or focused, and keeps the newest few.

Example

Polite toast
Source
<hui-toast politeness="polite" duration="100000">
<div data-toast>Saved</div>
</hui-toast>

The Go template that renders it:

<hui-toast politeness="{{ .Politeness }}" duration="{{ .Duration }}">
{{ range .Messages }}
<div data-toast>{{ . }}</div>
{{ end }}
</hui-toast>

API

Attributes3
Attributes
NameTypeDefaultDescription
politeness"polite" | "assertive""polite"Politeness of the live region: polite renders a role="status", assertive a role="alert".
durationnumber5000Milliseconds before an item auto-dismisses. A positive data-duration on an item overrides it, and 0 disables auto-dismiss.
maxnumber3How many items to keep, newest first; older ones are removed.
Properties3
Properties
NameTypeDefaultDescription
politeness'polite' | 'assertive''polite'Reflects to the politeness attribute.
durationnumber5000Reflects to the duration attribute.
maxnumber3Reflects to the max attribute.
Events1
Events
NameDescription
hui-toast-dismissEmitted when an item is dismissed, with detail.item the element being removed. It bubbles and is composed.
Slots1
Slots
NameDescription
(default)The toast items. Mark one with data-toast to group it with a nested data-dismiss control, give it data-persistent or data-duration to tune its timer.
CSS custom properties5
CSS custom properties
NameDefaultDescription
--hui-popoveroklch(1 0 0)Background of a toast item.
--hui-shadow-lg0 10px 15px -3px oklch(0 0 0 / 0.1), 0 4px 6px -4px oklch(0 0 0 / 0.1)Elevation of a toast item.
--hui-duration-normal200msDuration of the enter and leave transitions.
--hui-easecubic-bezier(0.4, 0, 0.2, 1)Easing of the enter and leave transitions.
--hui-borderoklch(0.922 0.005 325.62)Border of a toast item.
::part() hooks1
::part() hooks
NameDescription
regionThe live region, a role="status" or role="alert" column with aria-live and aria-relevant="additions".

States

Assertive alert

politeness="assertive" interrupts a screen reader rather than waiting for a pause. It is for failures; everything else should stay polite.

Assertive alert
Source
<hui-toast politeness="assertive" duration="100000">
<div data-toast>Failed to save</div>
</hui-toast>

Persistent with a dismiss control

data-persistent keeps a message up until it is dismissed - the case for progress - with a data-dismiss control inside it.

Persistent with a dismiss control
Source
<hui-toast duration="100000">
<div data-toast data-persistent>
Uploading…
<hui-button size="icon" variant="ghost" data-dismiss aria-label="Dismiss"><svg width="16" height="16" aria-hidden="true"><use href="/doc/hui/hui-icons.svg#ri-close-line"></use></svg></hui-button>
</div>
</hui-toast>

Several messages

Several messages stack in the order the server rendered them, each with its own timer.

Several messages
Source
<hui-toast duration="100000">
<div data-toast>Saved</div>
<div data-toast>Invite sent</div>
<div data-toast>Export ready</div>
</hui-toast>

Server-side mechanics

The server owns the messages: it appends toast items as light-DOM children of <hui-toast>, one element per message, marked data-toast when the item groups a nested data-dismiss control. It must not own the live region, the politeness or the timing: the element supplies role="status" or role="alert", aria-live, and the auto-dismiss that pauses on hover and focus. It is not form-associated and submits nothing, and it has no public show or dismiss method, so a message is shown by sending markup and removed by the element's timer or a data-dismiss click. An hx-swap can append a new item out of band, which the live region announces; replacing the container itself while items are live discards their timers and pause state.

Accessibility

  • The region is aria-live="polite" or assertive with aria-relevant="additions", so appended messages are announced.
  • Auto-dismiss pauses on pointerenter and focusin and resumes on leave, satisfying WCAG 2.2.1 for time limits.
  • A dismissed item is marked data-dismissed and aria-hidden="true" before it is removed, so the fade is not announced.
  • When more than max items are present, the oldest are removed so the live region stays bounded.

Keyboard

Keyboard
KeysAction
TabMoving focus into a toast fires focusin, which pauses its dismissal; leaving resumes the timer.
Enter, SpaceActivate a data-dismiss control inside a toasted item to dismiss it, emitting hui-toast-dismiss.

Gotchas

  • There is no public show or dismiss method; dismiss is private, so the host shows a message by appending markup and can only trigger removal through a data-dismiss control or the timer.
  • Only the newest max items are kept, so older messages are removed as new ones arrive.