Toast queue
A transient confirmation that an action the clinician just took has completed. That is its entire remit — and the reason most of this page is about what it must never be allowed to carry.
Overview
A toast appears without being asked for and disappears without being dismissed. Those two properties make it good at exactly one job — telling a clinician that something they deliberately started has finished — and dangerous at everything else, because anything that can vanish unseen is unsuitable for information a clinician needs.
The test: if a clinician looks away for ten seconds and misses it entirely, is anything lost? If yes, it is not a toast.
Consequence of an action
A toast only ever confirms something the clinician just did. Nothing the system decided on its own appears here.
Losable by design
Missing one costs nothing, because everything it says is also recorded somewhere durable.
Never in the way
It occupies a corner, never the alert region, never a control, and it yields to anything clinical.
Never an alarm
No clinical finding is ever delivered as a toast — at any priority. A toast auto-dismisses, stacks out of view, and is invisible to a clinician facing the patient rather than the screen. A STEMI detection delivered this way can be missed completely, with no trace on screen that it ever appeared. Clinical findings are Alert Banners, which persist until acknowledged or resolved.
| Never a toast | Use instead |
|---|---|
| Any clinical finding or alarm, at any priority | Alert Banner, docked and persistent |
| Degraded input, lost source, failed analysis | Alert Banner at Advisory or Urgent |
| Anything needing a decision | Dialog |
| Validation errors | Inline, beside the field |
| Persistent state — "draft unsaved" | Status chip |
| Anything a clinician might need to re-read | Anywhere durable |
What it is for
Each confirms something a clinician deliberately did, and each is also recorded durably. Missing all three costs nothing.
| Element | Rule |
|---|---|
| Title | What completed, in the past tense. "Cath lab notified", not "Notifying…". |
| Meta | Time, and where the durable record is. This is what makes the toast losable. |
| Dismiss | Always present. A clinician clearing the corner should not have to wait. |
| Accent | Teal for success, neutral otherwise. Never an IEC alarm hue — see Colour. |
Behaviour
- Bottom-right, outside the alert region. Never top, never centre, never anywhere it can overlap an alarm or the patient header.
- Maximum three visible. Beyond three, the oldest leaves. There is no overflow indicator, because none of it matters enough to count.
- Dismiss after 6 s, paused on hover or focus. Long enough to read at a glance, short enough not to occupy the corner.
- Never covers a control. The corner is reserved; content does not flow under it.
- Never re-announces. One toast per action; repeated identical actions coalesce with a count.
- Suppressed while an unacknowledged Critical alarm is on screen. Nothing competes with an active alarm for attention, including good news.
Nothing may be communicated only by toast. Each one names where the permanent record lives — the event log, the audit trail, the record itself — and that record is written first. The toast is a convenience layered on top of durable state, never the state itself.
Confirms a completed clinician action and points at the durable record. Losing it loses nothing.
A clinical finding on a six-second timer, in the corner, in an alarm colour. If nobody is facing the screen it is gone without trace.
What the component enforces, and what it only asks for
A toast queue is mostly a set of refusals, and refusals are the kind of rule a type can hold. What it cannot hold is the durable record that makes a toast safe to dismiss.
| Rule | Held by | How |
|---|---|---|
| A toast cannot carry an alarm | The component | There is no alarm tone on the Toast type. A transient surface that disappears on a timer is not where an alarm condition may live.Asserted: ToastQueue: there is no alarm tone to pass |
| A toast cannot outstay its welcome | The component | durationMs accepts 4000 or 6000 and nothing else, so it cannot be held on screen long enough to start behaving like a record.Asserted: ToastQueue: a toast cannot be held on screen indefinitely |
| It never interrupts a screen reader mid-sentence | The component | aria-live="polite" with aria-relevant="additions".Asserted: ToastQueue: the region is polite, never assertive |
| Hovering holds it | The component | The dismissal timer pauses on pointer enter, so a toast cannot expire while it is being read. Asserted: Toast: dismisses itself, and pausing on hover holds it |
| A busy screen does not keep a toast alive | The component | The timer reads the latest onDismiss rather than restarting whenever it changes. Callers pass it inline, so every parent render restarted the clock and on a screen with a live value a toast never left. Driven in a browser.Asserted: Toast: a parent re-rendering does not keep a toast alive |
| The close control is named with the word it shows | The component | “Close: Note saved”, on a button reading “Close”. It was named “Dismiss: …”, which fails WCAG 2.5.3: a speech-input user says the word they can see. Asserted: AX tree: the toast's close control is named with the word it shows |
| Everything it says also exists somewhere durable | You | The component cannot check that. A toast is a courtesy copy; if it is the only place a confirmation appears, the confirmation is gone in four seconds. |
| Nothing actionable lives only here | You | You choose what to put in a toast. A control whose only home is a surface that dismisses itself is unreachable by anyone who looked away. |
| Toasts do not queue faster than they can be read | You | The array is yours. Five arriving at once is five that nobody read. |
A rule stated on a component page reads as a rule the component keeps. 4 of these 7 are; 3 are obligations this page was quietly handing to the reader. The rule that matters most — that a toast is a copy of something durable — is unverifiable from inside a renderer, and it is the one that decides whether dismissing one costs anything.
Do's and don'ts
Confirms a completed clinician action and names its durable twin. Missing it costs nothing.
A clinical finding on a six-second timer. Face the patient instead of the screen and it is gone without trace.
Note saved · 14:32:07
also in the event log
A courtesy copy of something durable. Dismissing it, or missing it, costs nothing.
Cath lab notified · 14:32:07
(only here)
The only record that the cath lab was called, on a surface that dismisses itself in four seconds. A clinician who looked away now has no way to know whether the call was made.
Accessibility
role="status", neverrole="alert". Toasts are polite by definition; anything warranting assertive announcement is not a toast.- Never steals focus. Focus stays where the clinician put it.
- Reachable by keyboard through a documented shortcut that moves to the toast region, so a keyboard user can dismiss without a pointer.
- Auto-dismiss pauses on hover and on focus, so a magnified or slower reader is not timed out mid-sentence.
- Under
prefers-reduced-motiontoasts appear without sliding. The timer is unchanged. - Contrast. Rendered on
--popoverwith a border; it never relies on the shadow to be distinguishable from the content beneath.
Outcomes of use
What this contributes to, in the terms of Usability & context of use. These are attributes believed to contribute to an outcome; the outcome itself is settled by observing real use in a specified context, not by this page.
- Effectiveness — nothing depends on a toast being seen, by construction. Its contribution is confirming that an action landed, so it is not repeated.
- Efficiency — removes the check-whether-it-worked step after an action, without occupying the screen permanently.
- Satisfaction — closure. An action that produces no visible response is experienced as uncertain, and uncertainty after notifying a cath lab is expensive.
Clinical safety notes
Trace these in your risk file (ISO 14971) and usability engineering file (IEC 62366-1). Which of these the component keeps and which are yours is stated in the guarantees table; a control the component does not keep is one your risk file must show you keep.
- No clinical finding may be delivered as a toast. (the component) Mitigates: a detection auto-dismissing unseen, leaving no trace on screen.
- Every toast has a durable record. (you) Mitigates: information existing only in a transient surface.
- No IEC alarm hues. (the component) Mitigates: a transient element being read as an alarm, and dilution of the alarm palette.
- Suppressed during an unacknowledged Critical alarm. (you) Mitigates: attention competition at the worst moment.
- Never overlaps the alert region or a control. (you) Mitigates: an alarm or action obscured by a confirmation.
- Polite, never assertive; never steals focus. (the component) Mitigates: interruption of a clinician mid-task by a confirmation.
- Timer pauses on hover and focus. (the component) Mitigates: timing out a reader who needs longer.
Implementation
$ npx shadcn@latest add https://md.notjustany.tech/r/toast-queue.json
// There is no toast.confirm(). This page published an imperative API
// that does not exist, and neither the samples nor the props rule
// could see it: toast.confirm is lowercase and never a JSX tag.
<ToastQueue
toasts={toasts} // each carries its own id, title and durable record
onDismiss={(id) => setToasts((t) => t.filter((x) => x.id !== id))}
/>
// durationMs accepts 4000 or 6000 and nothing else, so a toast cannot
// be held on screen long enough to start behaving like a record.
What the component takes. This table used to list title, recordedIn, tone, duration — props the component does not have, and never had. Found by the registry gate’s props-table rule.
| Prop | Type | Default | Notes |
|---|---|---|---|
toasts | Toast[] | — | Required. Each an id, a title, an optional description, and a tone of info or ok — there is no alarm tone. |
onDismiss | (id: string) => void | — | Required. Called when a toast times out or is closed. Writing it somewhere durable first is yours. |
durationMs | 4000 | 6000 | 4000 |
Four or six seconds, and nothing else. Long-lived toasts are how a queue starts pretending to be a record. |
Related
- Event log — the durable record a toast is a courtesy copy of. Without one, dismissing a toast costs everything it said.
- Alert Banner — anything clinical, and anything persistent.
- Status chip — persistent state on a row or card.
- Dialog — anything requiring a decision.
- Acknowledge & escalate — why alarms cannot auto-dismiss.
- Messaging — the general rule these prohibitions are the specific case of: transient means safe to miss.