J3W1 / DESIGN SYSTEM
Toast
A brief notification in a fixed corner stack; canvas surface behind a 1px overlay border, status tints for the four polite statuses and the danger fill for critical ones.
stable · LIGHT DOM · 1.1.0
Light DOM retains static content, native semantics, label relationships and host composition without duplicating controls.
Live variants
default
Settings saved.
<j3w1-toast id="example-toast-default"><div class="toast-stack" role="region" aria-label="Notifications">
<div class="toast" role="status">
<span class="toast-glyph" aria-hidden="true">i</span>
<p class="toast-text">Settings saved.</p>
<button class="toast-close" type="button" aria-label="Dismiss">✕</button>
<span class="toast-count" aria-hidden="true">+2</span>
</div>
</div></j3w1-toast>status
Connection lost. Changes are queued.
Battery at 10%.
Screenshot copied.
Workspace 3 moved to the left output.
Layout locked.
<j3w1-toast id="example-toast-status"><div class="toast-stack" role="region" aria-label="Notifications">
<div class="toast toast-danger" role="alert">
<span class="toast-glyph" aria-hidden="true">✕</span>
<p class="toast-text">Connection lost. Changes are queued.</p>
<button class="toast-close" type="button" aria-label="Dismiss">✕</button>
</div>
<div class="toast toast-warning" role="status">
<span class="toast-glyph" aria-hidden="true">!</span>
<p class="toast-text">Battery at 10%.</p>
<button class="toast-close" type="button" aria-label="Dismiss">✕</button>
</div>
<div class="toast toast-success" role="status">
<span class="toast-glyph" aria-hidden="true">✓</span>
<p class="toast-text">Screenshot copied.</p>
<button class="toast-close" type="button" aria-label="Dismiss">✕</button>
</div>
<div class="toast toast-info" role="status">
<span class="toast-glyph" aria-hidden="true">i</span>
<p class="toast-text">Workspace 3 moved to the left output.</p>
<button class="toast-close" type="button" aria-label="Dismiss">✕</button>
</div>
<div class="toast toast-neutral" role="status">
<span class="toast-glyph" aria-hidden="true">·</span>
<p class="toast-text">Layout locked.</p>
<button class="toast-close" type="button" aria-label="Dismiss">✕</button>
<span class="toast-count" aria-hidden="true">+2</span>
</div>
</div></j3w1-toast>with-action
Window closed.
<j3w1-toast id="example-toast-with-action"><div class="toast-stack" role="region" aria-label="Notifications">
<div class="toast" role="status">
<span class="toast-glyph" aria-hidden="true">i</span>
<p class="toast-text">Window closed.</p>
<button class="toast-action" type="button">Undo</button>
<button class="toast-close" type="button" aria-label="Dismiss">✕</button>
<span class="toast-count" aria-hidden="true">+2</span>
</div>
</div></j3w1-toast>Install and register
Use the exact version. If npm publication is pending, install the release tarball from the installation guide.
npm install --save-exact @j3w1/ui@1.1.0import '@j3w1/ui/tokens.css';
import '@j3w1/ui/styles/toast.css';
import '@j3w1/ui/register/toast';Insert the maintained markup above after loading these imports. Its native children provide accessible names and form behavior; the empty custom tag alone does not create a control.
Copy the complete implementation
npx --package=@j3w1/ui@1.1.0 j3w1-ui copy toast --out ./vendor/j3w1/toastThe CLI verifies every file before writing and refuses overwrites. Serve the output over HTTP and open index.html. Keep its modules, CSS, tokens and licence notices together.
Public API
attributes
| Name | Type / signature | Meaning |
|---|---|---|
disabled | CustomEvent | Disable the native controls owned by this instance. |
loading | CustomEvent | Mark the primary control busy and prevent duplicate activation. |
properties
| Name | Type / signature | Meaning |
|---|---|---|
disabled | boolean | Delegates disabled state to native children. |
name | string | Native control name; application form keys remain explicit. |
methods
| Name | Type / signature | Meaning |
|---|---|---|
refresh | (): void | Reconnect behavior after replacing native child structure. |
focus | (options?: FocusOptions): void | Focus the first usable native control. |
dismiss | (id?: string): void | Dismiss a message; focused actions move to the next available control. |
events
| Name | Type / signature | Meaning |
|---|---|---|
j3w1-dismiss | CustomEvent | Cancelable message dismissal. |
j3w1-retry | CustomEvent | Request recovery; the host owns the result. |
j3w1-action | CustomEvent | An explicit message action. |
Dependencies and verification
Registered components: none. Style dependencies: none.
Package presence establishes an available implementation. Actual passes depend on the tested artifact and environment. Read specification execution evidence; read packed-consumer evidence; inspect the complete state matrix.
Full implementation manifest, API and token dependency closure
Canonical specification
Purpose
A short confirmation or notice that does not belong to any one element on the page: “Saved”, “Copied”, “Connection lost”. It appears in a fixed corner stack, is announced politely, and leaves on its own after a pause or when dismissed. Anything that needs a decision is a dialog; anything tied to a form is an alert.
Anatomy
The stack region; each toast on color.surface.canvas behind a 1px
color.border.overlay, or on a status tint with its status border; the glyph
and the text; an optional action; the Dismiss button; the “+n” count. The
danger toast is the historical critical notification: color.status.danger.fill
with color.status.danger.on-fill for the text, the glyph and both buttons.
States
| State | Visual | Non-colour channel |
|---|---|---|
| default | canvas surface, 1px overlay border, glyph in the status text colour | the glyph; the worded text |
| hover | action → color.interaction.hover.bg-strong with color.text.link-hover; Dismiss → color.action.tertiary.hover-bg; the timeout pauses | cursor: pointer; underline thickens on the action |
| focus-visible | ring 1px dashed color.interaction.focus.ring at −2px on the focused button; on the danger fill the ring takes color.status.danger.on-fill; the timeout pauses | the ring |
| stacked | toasts sit in one column with a 4px gap, newest at the end; the last visible toast shows “+n” in color.text.muted for queued ones | the count text; at most three visible |
| reduced-motion | no transition; the toast is simply present or absent | prefers-reduced-motion; nothing moves |
The toast has no disabled, selected or busy state.
Keyboard
Toasts never take focus when they appear. A host shortcut (F6 on the web reference) moves focus into the region; Tab then walks each toast’s action and Dismiss; Escape dismisses the focused toast. While any toast has focus or the pointer, its timeout is paused.
Accessibility
The region is named “Notifications”; each toast is role="status" so it is
announced politely, and danger toasts are role="alert". The text states the
outcome in words and the glyph is aria-hidden. Every toast has Dismiss and
the timeout is at least 8 seconds, extended for toasts with an action; an
action is never the only way to reach what it does. Contrast: text 8.65:1 on
the canvas, the overlay border 4.69:1, status text on its tint from 5.31:1
(neutral) to 6.59:1, on-fill text 4.58:1 on the danger fill, which is itself
4.14:1 against the canvas.
Portability
A fixed region, tints, 1px borders and text glyphs. Hosts with a notification daemon send the text and urgency instead of drawing a toast; the danger fill maps to the critical urgency. Toolkits with a native toast overlay use it and record that the danger fill is not available.
Non-examples
A toast that slides in from an edge. A rounded, shadowed pill. A toast with no Dismiss that vanishes after two seconds. A toast that takes focus on appearance. Stacking more than three with no count. A form error shown as a toast. Colour-only status without the glyph and worded text.