Skip to main content
First-pass proposal, not established policy. No audited Invoca screen backs this page — Titan’s design library was not available while writing it. It is built from general interaction-design practice and from what Toast, Alert, and Banner already establish.One piece of this page has no component behind it at all: the idea of a lightweight in-app notification indicator for something that happened while the reader was elsewhere. That is flagged explicitly below, as a proposal with nothing shipped — not as an existing part of Titan. Banner itself is also unshipped; its own page documents that as a checked, real absence, not an unwritten stub.

The problem

Something happens, and the interface has to tell the reader — but “something happened” covers wildly different situations. The reader just clicked Save and needs a quick confirmation they can miss without consequence. A campaign’s routing has been degraded for an hour and every page they visit should say so until it’s fixed. A field they’re editing right now is invalid. An export they started five minutes ago, before navigating to a different screen entirely, has just finished. Titan ships two of the four components this needs — Toast and Alert — with clear jobs and no shared vocabulary for choosing between them at the composition level. It ships zero for the third: a persistent, page-independent condition. And it has no answer at all for the fourth: telling someone about something that finished outside the view they’re currently looking at. Using the wrong surface for the wrong situation has a real cost in both directions. A toast for a billing problem disappears in five seconds and the reader never sees it again. An alert used for “your change was saved” becomes furniture nobody reads, sitting in the exact spot where the next real problem needs to appear.

Decide first: whose action, and how long does it matter?

When this applies

  • Deciding which surface tells the reader about an outcome, a standing condition, or something that finished outside their current view.

When it doesn’t

Structure

Behavior

Constraints

Content

Accessibility

A toast’s 5-second default may not give a screen-reader user enough time to hear a longer message. This is not a proposal fix — it’s a real, documented limitation of the shipped component. Pass persist: true for anything longer than a short confirmation, per Toast’s own accessibility notes. An Alert’s live-region role depends on when it appears. Set role="alert" for a message that must interrupt now, and role="status" for one that can wait for a pause — never role="alert" on an alert present at page load, since a live region with content already in it on load announces nothing. See TITAN-ALR-08. An in-app notification indicator (proposal) should announce a changed count politely, not interrupt. An unread badge changing from 1 to 2 is not urgent enough to cut off whatever the reader is doing — aria-live="polite" on the count, not "assertive".

Variations

Anti-patterns

A toast for something the reader wasn’t there to see. A background export that finishes three screens after the reader navigated away fires a toast into an empty view. Nobody reads it, and the outcome is lost the moment it appears. An Alert doing a Toast’s job. A success alert that stays on screen after the reader has moved on becomes part of the furniture — they stop reading it, and it occupies the exact space the next real problem needs. A home-grown banner per team. With no shipped Banner, the temptation is to compose one from Alert’s tokens inside a single feature, which produces as many visual treatments for “account-wide condition” as there are teams that have needed one — the same failure mode TITAN-GAP-31 already recorded for skeleton screens. Silence for background work. Shipping nothing for “this finished while you were elsewhere” is a real answer, but an accidental one — the reader is left to notice a change on their own, or not notice it at all.
Last modified on September 7, 2026