A wider screen, please

This page features interactive demos and side-by-side code samples that need at least 340 pixels of horizontal space. Please widen your browser window, or rotate your device, to continue.

Morpheus v0.1.0
v0.1.0

Toaster#

Component <neo-toaster> is a stack of transient notifications. One instance typically lives in the app shell; show toasts programmatically via the window-attached NeoToast API, or server-side by morph- patching <neo-toast> children into the toaster. Hover or click a toast to pause its auto-dismiss; × dismisses immediately.

Default
Variants
Title + description
Stack + dismiss-all
Deactivate Rename Duplicate
Delete
New state Toggle autoplay
Success Info Dismiss all Example Toast Toast created! Will self-destruct in 2s... Edit Toasts in the Playground Edit my contents in the HTML panel below ⬇︎ Error Toast This one you have to dismiss manually.
HTML CSS

The selected state's markup and its scoped CSS. The CSS is wrapped in <style>@scope { ... }</style> and applies to the preview only. Edits change the preview above, applied live while Sync is on, or when you click Patch or Replace. Patch morphs the preview; Replace swaps it outright.

Replace Patch

Signals

Datastar signals declared in the selected state's markup. Change a value to drive the preview, applied live while Sync is on, or when you click Patch.

Patch

Reference#

Attributes #

NameTypeDefaultDescription
position"top-right" | "top-left" | "top-center" | "bottom-right" | "bottom-left" | "bottom-center""bottom-right"Stack anchor relative to the viewport.
containedbooleanfalseAnchor to the nearest positioned ancestor instead of the viewport. Omit for fixed positioning.
stacknumber observed00 shows every live toast as a normal vertical stack. Positive values show that many full toasts, then up to two older toasts as hidden-behind peek cards; the rest appear when the toaster is hovered, focused, or clicked.
touch-dismiss"off" | CSS lengthonTouch swipe-to-dismiss is on by default. Set touch-dismiss="off" to disable, or pass a CSS length (for example 8ch, 4rem, or 40%) to override the default threshold of one third of the toast width, minimum 40px.
<neo-toast> variant"default" | "success" | "error" | "warning" | "info" | "loading""default"Variant for a declarative toast child. Adds the matching icon/accent; error uses assertive live-region semantics.
<neo-toast> durationnumber0Auto-dismiss delay in milliseconds for a declarative toast child. Positive values arm the timer; missing, zero, or negative values stay pinned.
<neo-toast> dismissible"false"noneSet to false on a declarative toast child to omit the close button and disable touch swipe dismissal for that toast.

States #

NameDescription
:state(expanded)Set while the stack is unfolded (hover, focus, or click). Dismiss timers are paused for as long as it holds.

Slots #

NameDescription
<neo-toast>Declarative toast children. Slot names inside each toast: title, description, action, icon. Imperative API: NeoToast.show({...}).

CSS variables #

NameDefaultDescription
--neo-toaster-z-index1200Stacking order of the fixed toaster relative to the rest of the page.
--neo-toaster-padding1remInset between the toaster stack and the viewport edge.
--neo-toaster-max-width22remMaximum width of a toast card.
--neo-toaster-gap10pxVertical gap between toasts in the expanded stack.
--neo-toaster-stack-offset14pxVertical offset between peek cards in the collapsed stack.
--neo-toaster-stack-scale-step0.05Scale reduction applied per peek card behind the freshest toast.
--neo-toaster-transitioncalc(400ms * var(--neo-duration-scale, 1)) var(--neo-easing, cubic-bezier(0.32, 0.72, 0, 1))Transition timing for toast transform and opacity.
--neo-toaster-max-heightcalc(100dvh - var(--neo-toaster-padding) - var(--neo-toaster-padding) + var(--neo-toast-shadow-bleed) + var(--neo-toast-shadow-bleed))Maximum height of the expanded scrollable stack.
--neo-toast-bgvar(--btn-bg)Toast card background.
--neo-toast-fgvar(--page-fg)Toast text color.
--neo-toast-bordervar(--btn-border)Toast border color.
--neo-toast-radiusvar(--page-radius, 0.5rem)Toast corner radius.
--neo-toast-shadow0 8px 24px -10px rgba(0, 0, 0, 0.22), 0 2px 4px -2px rgba(0, 0, 0, 0.08)Toast box shadow.
--neo-toast-shadow-bleed1.5remExtra space reserved around the stack so the toast shadow is not clipped.
--neo-toast-successoklch(0.65 0.18 145)Accent color for the success variant icon.
--neo-toast-errorvar(--danger-bg)Accent color for the error variant icon.
--neo-toast-warningoklch(0.78 0.16 80)Accent color for the warning variant icon.
--neo-toast-infooklch(0.6 0.18 240)Accent color for the info variant icon.

Examples#

Show a toast (vanilla JS)#

No framework: a plain addEventListener('click', …) handler calls the toaster instance's show() method directly. The window-attached NeoToast.show() targets the page-wide singleton at the bottom-right of the viewport; for a contained preview, talk to the element. The toast inherits hover-to-pause, swipe-to-dismiss, and live-region semantics without any extra wiring.

Show toast

Examples: Datastar#

The toaster also works declaratively: drop <neo-toast> children into the host (server-side renders or patched in by Datastar SSE datastar-patch-elements events) and a MutationObserver picks them up, wires their lifecycle, and animates them in. Each demo below ships the exact handler under Server script; see also the SSE events reference.

Touch dismissal is on by default. Set touch-dismiss="off" to opt out or a CSS length like touch-dismiss="8ch" to override the threshold. Individual toasts with dismissible="false" skip the close button and the swipe gesture. contained anchors the toaster to its parent, so previewed toasts paint inside the demo frame.

Triggers the app-shell toaster#

Show toastDismiss app toasts

Patch: append a toast#

An SSE patch-elements event with mode: "append" drops a new <neo-toast> into the toaster's stack. The new card is the freshest in the stack and auto-dismisses after its duration (3 s here).

Append toast

Patch: replace all#

An mode: "inner" patch on the stack wrapper replaces every child. Existing toasts get destroyed (the MutationObserver fires on each removal and runs the leave animation) and the new batch animates in. The Pin button is its own mode: "append" endpoint that seeds something for Replace to overwrite.

Pin oneReplace all

Patch: update one toast#

The toaster is SSR'd with one pinned toast and stack="1" (single visible toast). Clicking Update title streams an SSE patch-elements event keyed by the title node's id (#patch-update-toast-title). The toast element keeps its identity (and its dismissal timer); only the inner text changes.

Update titleOriginal title Click "Update title" to morph this label.

Loading + async patch#

The loading variant defaults to duration 0 (persistent) and renders a <neo-spinner> instead of a static icon. These buttons use Datastar actions: the simulator patches a loading toast immediately, waits on the server side, then morphs that same toast to the final success or error state.

CreateResolveReject

Action button#

Action buttons can be rendered by the server too. This example patches a toast with an Undo button whose click is a Datastar action; the undo request then appends a related confirmation toast with its own unique id.

Archive

Variants#

Only the icon picks up the variant accent, so the card itself stays neutral. error raises the live-region politeness to assertive so screen readers announce it immediately.

SuccessErrorWarningInfo

Title + description#

Pass an object with both title and description to get a two-line layout. Description text uses the muted colour and a smaller size, so the title remains the primary label.

Show

Stack + dismiss-all#

NeoToast.dismiss() with no argument closes every active toast at once: a "clear all" button, or to wipe a backlog between scenarios.

Stack fourDismiss all

Settings

Theme

Default Sunshine Ocean Matrix Rose

Accessibility

Playgrounds

Server Simulator