What this is
One accent hue in, a whole token set out, for both schemes. Everything on this
page is drawn with the tokens shown below it, so what you see is the output
and not a picture of it. Pick a hue in the bar — including one no product uses
yet — and the planes, the three text weights, the accent family and the
danger family are all re-derived, contrast-solved, and re-checked live. The
components are no more a picture than the tokens are: this page imports the
same components.css a product imports beside its token file.
Planes
Each plane sits on the one before it. The hue is the product's own, held at a very low chroma, so the neutrals read as one material rather than as grey with a cast dropped over it.
Text
--text is a fixed point on the ramp. --text-dim and
--text-faint are solved against --surface-2
— the fill of every field, and the tightest ground either really sits on.
Solving against --bg instead is what once shipped a
--text-faint that measured 3.92:1 where it was checked and 3.18:1
where it was printed.
Accent and danger
--accent is exactly what the product declared and is never
adjusted. The other four follow from it. --accent-ink tries both
near-black and near-white and keeps whichever wins on that hue — hardcoding
one is how a delete-everything button shipped at 2.48:1.
Contrast audit
Every pairing the token table promises will clear AA, measured on the values
above. build.js runs this same check and refuses to write a file
that fails, so a ratio can only regress if somebody hand-edits generated CSS.
| Foreground | Ground | Ratio | Needs |
|---|
Buttons
Three tiers, no more. Primary takes the accent fill and there is one
per view. Normal is --surface-2. Quiet is
transparent. Destructive is not a fourth tier but a colour applied to a quiet
or normal button — only the confirm button of a destructive dialog is filled.
Tiers
Segmented
One row of mutually exclusive choices, the live one lifted out of the
track. The track is --bg and the lifted segment is
--surface — the only pairing that reads as raised in both
schemes, because that is precisely what --surface means.
Selection rides aria-pressed; below 560px the row wraps into
two columns rather than crushing its labels.
Fields
A field is a fill, not a hole. At rest it is --surface-2 with a
transparent border; on focus the fill lifts to --surface, the
border takes the accent, and the ring appears. font: inherit,
always — a sentence typed in must look like the same sentence read back out.
Chips
Filters are pills, actions are boxes. A chip changes what is shown and never
what is stored. The count sits at opacity: .55 in tabular
numerals; the selected one takes the accent tint, never the full fill — the
full fill belongs to the primary action alone.
Rows and the overflow menu
A row shows its content and one ⋯. What it says about
itself may be clickable, but everything you can do to it lives behind
that one trigger — and never behind hover, because these products are used on
touch screens. Destructive rows sit last.
Folded panels
A settings block states its status in a sentence before it offers a
control — so the heading carries the state, a look is enough, and opening
is a decision. Native <details>, which is why this
component needs no JavaScript from the product at all. The accent tint
marks the current one, and a summary never holds a button: a control
nested in it would toggle the panel it sits in.
ARASAAC Aktive Quelle · rund 13.000 Piktogramme
Free pictograms, nothing to set up. The body is where the controls live.
METACOM 67952 Symbole · METACOM_9_Desktop
Licensed, read locally.
Funktionswörter 128 Wörter
One word per line.
Messages and empty states
Four kinds of message, four treatments. Progress belongs to the control that started it. Outcome stays until something replaces it and is never auto-dismissed if it names a failure or a number. Aside acknowledges something already visible and may clear itself. A standing line reports a condition that persists between visits — the only one that can change while nobody is looking. An empty list teaches; a filtered-empty is a different, shorter sentence.
The standing line, in every state it has. The dot answers one question —
is it writing? — so there is no amber: permission that needs
re-confirming means nothing is being written, which is the same news as a
failure. Both of those states carry the age of the last good copy, because
„it is not working" is a sentence somebody can put off and „nothing saved
for eleven days" is not. data-state takes
@lautstark/sicherung's status kind verbatim.
No folder chosen yet.
Folder „Sicherungen" · saved 3 minutes ago
Saving …
Access to „Sicherungen" must be confirmed — last saved 11 days ago.
Backup failed: no space left on device — last saved 11 days ago.
Destructive confirmation
Name what is lost and label the button with the act, never "OK". The body states the count and what does not come back.
Delete 12 sentences?
Their recordings go too. This cannot be undone — a backup exported before now is the only way back.
The generated file
What build.js writes into each product, header and all. Nothing
here is hand-maintained.