NockerlToast renders ONE toast from a NockerlToastProps object plus an onClose
(timer / Esc / close-X) and an optional onAction (the action button). The corner
viewport + the stack (spawn / remove / cap) are the app’s. Mount the cards where you
want them; the toast owns its own countdown, hover/focus pause, and Esc dismissal.
Prop
Type
Default
Description
message *
string
n/a
Body copy that carries the toast's accessible text (rendered as HTML).
onClose *
() => void
n/a
Dismiss handler, fired when the timer elapses, Esc is pressed, or the close (X) is clicked.
intent
NockerlToastIntent
'info'
Drives the status color, the default icon, and the live role.
title
string
n/a
Optional bold heading above the message (one short line).
icon
boolean
true
Show the leading status disc (defaults to on).
actionLabel
string
n/a
Optional quiet text button in the status color (right-aligned; e.g. Undo).
onAction
() => void
n/a
Action handler (ignored when no actionLabel).
duration
number
n/a
Auto-dismiss after this many ms. 0 / undefined → PERSISTENT (no timeout); the toast then shows a "pinned" marker instead of the ring and waits for close.
NockerlSnackbarHost is the proposed Compose host: a corner-anchored stack of
NockerlSurfaces (panel radius + the lit-from-above material) washed with the
intent’s status color, the same errorContainer treatment generalised. State is
driven by rememberNockerlSnackbarState(), mirroring SnackbarHostState.
Parameter
Type
Default
Description
message *
String
n/a
Body copy, rendered with bodyMedium on the card foreground.
intent
NockerlSnackbarIntent
INFO
Status intent: INFO · SUCCESS · WARNING · ERROR. INFO is the only cyan; the rest are warm status tokens.
title
String?
null
Optional heading (one line) above the message, in the status color.
showIcon
Boolean
true
Show the leading status icon (top-aligned). Color is paired with the icon + text, never alone.
actionLabel
String?
null
Optional action: a GHOSTNockerlButton in the status color. Tapping it resumes the suspend show() with ACTION.
duration
NockerlSnackbarDuration
SHORT
Auto-dismiss window: SHORT · LONG · INDEFINITE. INDEFINITE is persistent (a pinned marker; waits for close). A countdown rides the bottom edge.
withDismissAction
Boolean
true
Show a trailing dismiss NockerlIconButton, a separate focusable target. Resumes show() with DISMISSED.
NockerlToast is the proposed SwiftUI generalisation of the shipped RecordingHUD:
a non-activating, focus-safe overlay surface tinted by the intent’s NockerlTheme
status token, stacked in a corner by .nockerlToastHost(center:position:) and
auto-dismissed on a timer.
Style
Type
Default
Description
show(_:intent:)
Void
n/a
Enqueue a toast: the message + intent (.info / .success / .warning / .error). .info uses NockerlTheme.accent (cyan); the rest use warm status tokens.
title:
String?
n/a
Optional heading above the message, in the status color. Defaults to nil.
showIcon:
Bool
n/a
Leading SF Symbol in the status color (e.g. exclamationmark.triangle.fill), top-aligned. Defaults to true.
action:
ToastAction?
n/a
Optional (label, handler) rendered as a quiet trailing .nockerlGhost button (e.g. Undo), right-aligned. Defaults to nil.
duration:
ToastDuration
n/a
.seconds(_) auto-dismisses (a bottom-edge countdown; hover pauses, echoing the HUD scheduleHide); .persistent waits for close. Defaults to .seconds(5).
.nockerlToastHost(center:position:)
View
n/a
Mounts the stack overlay near the app root and anchors it to a corner (.bottomTrailing by default, like the HUD). Non-activating, so it never steals focus.
Toast vs banner vs dialog
Three feedback surfaces, three jobs. Don’t reach for the wrong one:
Toast (this page): transient + floating + non-blocking. It appears in a
corner, stacks, auto-dismisses on a timer, and never takes focus. For
ephemeral confirmations (“Saved”, “Undo?”) and passing errors.
Banner: inline + persistent. It sits in the
layout and stays until the state clears or the user dismisses it. For ongoing
app state (read-only, degraded mode, an approval waiting).
Dialog: modal + blocking. It interrupts with a
scrim and demands a decision. For destructive confirms and required choices.
Cross-platform drift (tracked for reconciliation)
Web ships NockerlToast (@dizyx/nockerl-react). The Kotlin and Swift tabs document
the proposed native shape, designed from the laws plus the transient-message
vocabulary the apps already use. The divergences to reconcile when they land, tracked in
the Review queue:
Precedent differs sharply: Voice has a real transient floating overlay
(RecordingHUD, a non-activating NSPanel that auto-hides via scheduleHide,
1.8s for a result / 8.0s for an error, fades 0.22s/0.28s, status-tinted border +
neutral shadow, never steals focus). Android’s transient state is inline connection
“pills” plus the Inbox sheet rather than a floating card. This page proposes the
shared, stackable component both should adopt.
info intent color(ratified): info = cyan everywhere. Voice’s token set
gains status.info as a cyan alias (NockerlTheme.accent) so every platform carries
the full semantic vocabulary even where the value aliases.
Stacking + position: the agreed policy is max 3 visible, overflow collapses to
“+N”, FIFO. The Voice HUD may keep its one-at-a-time morphing presentation (Law 9) but
adopts the shared stack policy where it stacks.
Duration scale(settled): durations = an enum short / base / long /
persistent backed by ms tokens. Voice’s literal seconds and Compose’s Material
SHORT/LONG map onto the shared enum.