For designers
What opsinjs fixes, what it expects you to decide, and the handful of pages a designer actually needs.
Overview
Most design system documentation is written for the person who will type the import. This page is written for the person who decided what to import. More often in a health product, it is for the person arguing with a stakeholder about why a metric cannot be red.
Read this in about twenty minutes. It will not teach you the system; it will tell you which twelve pages are worth your time and which sixty are engineering reference you can safely ignore until someone asks you a question.
Start with what is already decided
The most useful thing to know early is how little latitude you have, and where. opsinjs fixes more than a typical design system does, deliberately, because in a health interface the consequences of local variation land on a reader who cannot tell that it was local.
Fixed, and not negotiable per screen:
- What a colour is allowed to mean. Category identity and clinical status are two independent axes, and the rule is that they never mix. The two colour axes is the one page to read first. If you read nothing else on this site, read that.
- The four clinical status levels, their words, their icons and their tone. Clinical status semantics.
- The contrast floor, and the fact that it is measured rather than eyeballed. The contrast floor.
- The material ladder has six named rungs, so a surface is a choice from an ordered set rather than a blur value someone typed. Materials.
- What motion may communicate. Never urgency, never state that is not also carried some other way. Motion in health UI.
Yours to decide, and expected to be:
- Which measurement matters most on this screen, and therefore what is largest. Hierarchy is a product decision.
- Category assignment. Which of your product's domains a metric belongs to, and whether you need a category the system does not ship. Category palettes.
- Copy. In a health product this is most of the design. Content and language.
- Density and rhythm within the space scale, and which responsive mode a layout targets. Responsive modes.
- Brand. Theme generator takes a brand colour and derives a gamut-aware, contrast-validated system from it, and tells you when your brand colour cannot carry the meaning you want it to.
Learn the one rule that changes your work most
Category identity answers which part of my health is this? Status answers how concerning is this? They are rendered on different visual channels, and they are never allowed to trade places.
The practical consequence, and the thing that will come up in your first review: a category colour may never be chosen to imply that something is good or bad. If your Sleep category is a calm blue, a bad night does not turn the blue amber. The amber belongs to the status axis, appears in a different place, and arrives with a word and an icon beside it.
This is unusual, it will feel restrictive for about a week, and it is the reason
an opsinjs screen can be read correctly by someone who is colour-blind, on a dim
screen, in a hurry, or frightened. The interactive demonstration is
StatusAxisDemo, which refuses to render a mixed pair and explains why. It
lives on The two colour axes and in the
status playground.
Design against the accessibility floor, not after it
Four checks belong in your file, not in a QA pass at the end. All four are things you can do in a design tool today, before anything is built.
Design at 200% text
This is not an afterthought variant. It is a second artboard you keep in step. Dynamic Type at 200% is the single most common way a health layout breaks, because health layouts are full of large numbers next to small labels. Text resizing and zoom.
Check every state in greyscale
If the meaning survives greyscale, colour is doing its proper job of reinforcing something else. If it does not, you have encoded meaning in hue alone and a substantial minority of your readers cannot see it. Colour independence.
Measure your targets
Small controls next to health data are a particular hazard, because the reader is often one-handed and often anxious. WCAG 2.2 SC 2.5.8 is the floor, not the target. Target size.
Name the focus order
Reading order and announcement order are design decisions with a right answer: label, value, unit, status, time. If your composition makes status arrive first, a screen-reader user hears the alarm before they hear what it is about.
Hand it over without a translation layer
Tokens are the handoff. opsinjs publishes its token source as W3C DTCG JSON, which maps onto Figma Variables, so the names in your file are the names in the code rather than a parallel vocabulary that drifts. Design handoff covers the export, the mapping and the parts that do not survive the round trip.
Two things to agree with your engineers on day one:
- Nobody types a colour value. Not in the design file, not in the code. If a value appears in a review, that is the finding.
- A new category is a system change, not a screen change. Adding one is cheap and documented; inventing one locally is how the two axes get contaminated.
There is no Figma library yet
The design assets are the part that has not been built. Every catalogue row exists in code and the token source is real, but the DTCG export is specified rather than published, and there is no Figma file, kit or plugin. So a designer's route into the system today is this documentation and the rendered components, not a library you can drag from. Roadmap has the current state.
Verify it worked
Take one screen you have already designed and run it against these five. Ideally that screen is live. It takes about ten minutes and it is a more honest introduction to the system than any amount of reading.
- Greyscale it. Does every status distinction survive?
- Count the urgent surfaces. More than one is a defect. Alarm fatigue.
- Find the word normal. If it is there, it comes out. Reference ranges.
- Find a number with no timestamp. A health value without a time is ambiguous in a way that matters.
- Ask where each threshold came from. If nobody in the room can name the source, you have found the most important thing on the list.
Troubleshooting
"Our brand colour is the same red as the urgent status." Then your brand colour cannot appear on health surfaces at full strength, and the status axis wins. This is a real cost and it is worth surfacing early rather than at launch. Status palettes explains why redefining the status axis is the wrong fix and what to do instead.
"Marketing wants the dashboard to feel motivating." Legitimate, and mostly achievable through copy, hierarchy and category colour. What it cannot do is recruit the status axis: a green "great job" that uses the same green as a clinical status teaches the reader that green means praise, and then a genuine clinical green is misread.
"The system looks plainer than our brand." The documentation chrome is deliberately dense and square; the product theme is squircle, system-typeface and generous, and they are not the same thing. Lyra and the docs chrome explains the divergence, which is intentional and load-bearing.
"I need a component that does not exist." Check the catalogue first, which is usually faster than proposing one. Components, then Proposing a component.
Next
- The two colour axes is the page that changes the most about how your screens look.
- Foundations says what every token means, in the order a designer needs them.
- Accessibility for designers has the design-time checks in full, with how to run each one.