Roadmap
The public backlog is ordered, shows its blockers, and deliberately has no dates.
How to read this
This roadmap is ordered, not scheduled. There are no dates on it, and there will not be: a date on an unfunded backlog is a promise the project cannot keep, and the person most damaged by it is the one who planned a release around it. What you get instead is the order, the reason for the order, and the blocker attached to anything that is not moving.
The status of any individual component is not maintained here. It is generated from the catalogue, so it cannot drift from what the system actually contains.
Every component in this catalogue has been audited against WCAG 2.2 AA, and none has had an independent accessibility review or a clinical review. The phase word says how installable the source is and says nothing about review. Nothing here is for a production health surface until a clinician has signed it.
| Component | What a reader sees | Category | Phase | Also known as |
|---|---|---|---|---|
| ResultCardresult-card | One test result, showing the number, what it is compared against, and what it means. | Health data display | Shipped | results, lab result, test result, report card, blood pressure, a1c |
| RangeBarrange-bar | A bar showing where one reading sits against the range it is compared with. | Health data display | Shipped | reference range, normal range, in range, range indicator, gauge bar |
| ScoreDialscore-dial | A single composite number drawn as a ring, with the words that say what it counts. | Health data display | Shipped | dial, ring, gauge, score, index, bmi |
| TrendSparklinetrend-sparkline | A small chart of one reading over time, with an honest caption saying what changed. | Health data display | Shipped | sparkline, trend, over time, mini chart, line chart, chart, graph |
| MetricTilemetric-tile | A compact tile showing one reading, its unit and when it was taken. | Health data display | Shipped | stat, kpi, vitals, summary tile, steps, resting heart rate, spo2, tile |
| StatusPillstatus-pill | A short label saying what a reading means and what, if anything, to do about it. | Health data display | Shipped | chip, status chip, status badge, status label, traffic light |
| TimelineEntrytimeline-entry | One dated event in a vertical history. | Health data display | Shipped | history item, event list, activity feed |
| RangeLegendrange-legend | The key explaining what the bands on a range mean. | Health data display | Shipped | key, chart legend, band legend |
| AlertBanneralert-banner | A prominent message about something that needs the reader's attention now. | Health communication | Shipped | warning banner, notification banner, inline alert, warning, notification, alert, banner |
| CareCardcare-card | A card saying what to do next, and how urgently. | Health communication | Shipped | what to do next, action card, advice card, next steps, guidance card, what to do, advice |
| Termterm | A clinical word with its everyday meaning attached, so a sentence can be read without leaving it. | Health communication | Shipped | glossary term, jargon, plain word, definition, plain english, tooltip term |
| ConsentSheetconsent-sheet | A sheet that asks permission for one specific thing, and records the answer. | Health communication | Shipped | consent, permission, opt in, data sharing, agree |
| DisclaimerNotedisclaimer-note | The standing note about what this information is and is not. | Health communication | Shipped | disclaimer, not medical advice, legal note, small print, safety note |
| SourceCitationsource-citation | Where a piece of health information came from, and when it was last checked. | Health communication | Shipped | citation, evidence link, reviewed by |
| LogSheetlog-sheet | A form for writing down what happened today, in as few taps as possible. | Health input | Shipped | log, diary, journal, daily entry, capture, quick entry, bottom sheet entry |
| ReadingInputreading-input | An input for typing in a measurement, with the unit shown and switchable beside the number. | Health input | Shipped | enter a reading, measurement input, numeric entry, manual entry, numeric input, unit switch |
| BodyMapbody-map | A diagram of a body for pointing at where something hurts. | Health input | Shipped | pain map, anatomy diagram, where does it hurt |
| Valuevalue | One number and its unit, formatted the same way everywhere in the product. | Health formatting | Shipped | number, unit, format a number, numeric display, figure, format, formatted number |
| RelativeTimerelative-time | When a reading was taken, said the way a person would say it. | Health formatting | Shipped | time ago, timestamp, last updated, date display, ago, freshness, staleness |
| Tabletable | Rows and columns of data. | Data display | Shipped | data table, grid, rows and columns |
| Badgebadge | A small label attached to something else. | Data display | Shipped | counter, label chip |
| Surfacesurface | The base panel every other surface is built from, at one of six material rungs. | Surfaces | Shipped | material, glass, blur, elevation, layer, translucency, vibrancy |
| Cardcard | A bounded block of related content. | Surfaces | Shipped | panel, container, content box, box, tile group |
| Sheetsheet | A panel that slides over the screen and can be dismissed by dragging. | Surfaces | Shipped | bottom sheet, drawer, side panel, slide over, modal sheet, detent |
| Dialogdialog | A window that interrupts, for the one decision that cannot wait. | Surfaces | Shipped | modal, alert dialog, confirm, popup |
| Calloutcallout | A short piece of set-apart information that helps you understand what you are reading without claiming anything about your health, whether it is a note, a tip or a caveat. | Feedback | Shipped | admonition, note box, info box, tip, note, aside |
| EmptyStateempty-state | What a screen shows when there is nothing to show, and what to do about it. | Feedback | Shipped | no data, nothing here, zero state, blank slate |
| Skeletonskeleton | The shape of content that has not arrived yet. | Feedback | Shipped | loading placeholder, shimmer, ghost, loading state, placeholder |
| SegmentedControlsegmented-control | A small row of mutually exclusive options. | Navigation | Shipped | segmented buttons, toggle group |
| TabBartab-bar | The persistent bar of top-level destinations at the bottom of the screen. | Navigation | Shipped | bottom navigation, nav bar |
| Stepperstepper | Progress through a sequence of steps. | Navigation | Shipped | wizard, step indicator, multi step |
| Buttonbutton | The control that makes something happen. | Actions and forms | Shipped | cta, action, submit, primary button |
| Linklink | Navigation to somewhere else. | Actions and forms | Shipped | anchor, hyperlink |
| Fieldfield | A labelled input with its help text, its error, and the wiring that connects them. | Actions and forms | Shipped | form field, input wrapper, form control, validation message, label, error message, hint |
| IconButtonicon-button | A button whose only visible content is an icon. | Actions and forms | Shipped | glyph button, round button |
| Switchswitch | An on-or-off control that takes effect immediately. | Actions and forms | Shipped | toggle |
| Checkboxcheckbox | A box for choosing any number of options, including none. | Actions and forms | Shipped | tick box, multi select |
| RadioGroupradio-group | A set of options where exactly one can be chosen. | Actions and forms | Shipped | radio buttons, single choice |
| Selectselect | Choosing one option from a list. | Actions and forms | Shipped | dropdown, picker |
| NumberFieldnumber-field | An input for a number, with steppers. | Actions and forms | Shipped | stepper input, quantity input |
| Textareatextarea | A multi-line text input. | Actions and forms | Shipped | long text, notes input |
| Dividerdivider | A line separating two groups of content. | Layout | Shipped | separator, rule |
| Avataravatar | A picture or initials standing for a person. | Utility | Shipped | profile picture, initials, user image |
| VisuallyHiddenvisually-hidden | Content that screen readers announce and eyes do not see. | Utility | Shipped | sr only, screen reader only, clip |
| GoalRinggoal-ring | Progress towards a daily goal, drawn as a closing ring. | Health data display | Shipped | activity ring, close your rings, daily goal |
| ScaleInputscale-input | A one-to-ten scale for rating something like pain or mood. | Health input | Shipped | pain scale, rating scale, likert |
| DoseTrackerdose-tracker | A record of medicine doses taken and missed. | Health input | Shipped | medication, pill tracker, dose, adherence tracker |
| Questionnairequestionnaire | A multi-question form for a validated instrument such as a symptom score. | Health input | Shipped | survey, assessment, phq, screening form |
| SymptomPickersymptom-picker | A picker for choosing symptoms from a controlled list. | Health input | Shipped | symptoms, how are you feeling, symptom checker |
| Toasttoast | A brief message that appears and disappears on its own. | Feedback | Shipped | snackbar, transient message, notification toast |
| Progressprogress | How far through something the reader is. | Feedback | Shipped | progress bar, completion |
| Spinnerspinner | An indeterminate loading indicator. | Feedback | Shipped | loader, busy indicator, activity indicator |
| Tooltiptooltip | A short label that appears on hover or focus. | Overlay | Shipped | hover label |
| Popoverpopover | A small panel anchored to the control that opened it. | Overlay | Shipped | anchored panel, flyout |
| Menumenu | A list of actions opened from a button. | Overlay | Shipped | dropdown menu, context menu, overflow menu |
| Tabstabs | Switching between views that occupy the same space. | Navigation | Shipped | tab list, view switcher |
| Accordionaccordion | Sections that expand one at a time. | Navigation | Shipped | disclosure, expander, collapsible |
| Sliderslider | Choosing a value by dragging along a track. | Actions and forms | Shipped | range input, drag to set |
| Comboboxcombobox | A text input that filters a list as you type. | Actions and forms | Shipped | autocomplete, typeahead, search select |
| ScrollAreascroll-area | A scrolling region with styled scrollbars. | Layout | Shipped | scroller, overflow container |
The order, and why
Every component named below now exists, which is why this reads in the past tense. It is kept on the page because it explains the shape of what was built and which components lean on which, rather than because anything in it is still waiting.
1. Nothing shipped before the token layer was fixed. Every component reads semantic tokens, and every published contrast number describes a token pair. Renaming a token after twenty components consume it is the expensive mistake this project front-loaded to avoid, and everything built since was written against a token layer that had stopped moving.
2. The health data-display components came first, in this order:
StatusPill, RangeBar, ResultCard. They were ordered by how much of the
system they exercise rather than by how much anyone wants them. StatusPill is
the smallest complete test of the status axis and the colour-independence rule.
RangeBar is the first component that has to render a value against a range
without implying a diagnosis, which is the hardest content problem in the system.
ResultCard composes both and is the component most people arrive wanting.
3. Then the surfaces: Surface, Card, Sheet, Dialog. The material
ladder had been documented and tokenised with nothing climbing it, and a ladder
nothing climbs is a ladder nobody has tested. Those four exercise it now.
4. Then communication: AlertBanner, CareCard, Callout,
DisclaimerNote. These carry the alarm-fatigue budget, so they were built after
there was enough of a surface to measure a budget against.
5. Input and formatting last: ReadingInput, LogSheet, Value,
RelativeTime. Value is small and was tempting to do first; it was
deliberately late because its rounding and unit rules are doctrine that the
components above it sharpened.
What is next is not an ordered list, and inventing one would be the dated promise
this page opens by refusing. The honest statement is what has not been done: no
screen specimen has been built, and while every component has now been audited
against WCAG 2.2 AA by its own authors (see ADR 0025),
none has had an independent accessibility review or a clinical review. Every
catalogue row is implemented and installable. See Release phases
for what shipped obliges us to and, more to the point, what it does not.
Blockers
Some measurements still do not exist. Bundle sizes and the keyboard reference are generated pages whose sources are still empty. All sixty catalogue rows now record a WCAG 2.2 AA audit, run by the components' own authors and recorded in ADR 0025, but none records an independent accessibility review. Those pages are not missing, they are waiting on numbers nobody independent has produced. An audit table filled in by the people who wrote the code is not a passing one.
Colour-independence and the never-mix rule need a lint rule, not a document. The rule is written, and a rule that is only written is a rule that survives until the first deadline. Until the ESLint and Stylelint plugins described in Tooling exist, this is enforced by review, which is to say weakly.
Accessibility conformance cannot be claimed without an independent audit, and none has been run. Every component has now been audited against WCAG 2.2 AA by the people who wrote it, and the findings from that pass were fixed in the same change (see ADR 0025); that is not the same claim as conformance. The reason independent conformance still cannot be claimed is the ordinary one, that nobody independent has looked. The accessibility statement lists what is unknown today rather than implying it is fine.
The [lang] segment is not blocked, it is deferred, with the exact retrofit
recipe recorded in ADR 0005. Unit
systems are treated as a correctness problem and ship now, because getting those
wrong harms someone in English just as effectively as in any other language.
Those systems are mmol/L against mg/dL, kilograms against stones, and Celsius
against Fahrenheit.
What this project will not do
Saying no in public is part of a roadmap. None of the following is planned, and if you need one, opsinjs is the wrong dependency:
- Clinician-facing components. No EHR tables, no order entry, no prescribing. Density, training assumptions and error consequences are all different.
- A charting library. Data visualisation gives rules and an accessible chart contract; it will not ship a chart engine.
- A general form library.
Fieldexists to make health inputs correct, not to compete with the form libraries that already work. - A CLI.
npx shadcninstalls from our registry today and there is nothing a CLI of our own would add. Writing one before writing a component would have been building the shop before the stock; now that there is stock, the shop still belongs to somebody else, a choice recorded in ADR 0002. - Native mobile. The system targets the web, including web views in native apps. React Native is not on this list.
How something gets onto this page
Through Proposing a component, which sets out the eight questions a proposal has to answer and the four reasons one is normally declined. The short version: a name is cheap, a specification is not, and nothing is implemented before its clinical contract is written down.
Last read through against the system on 2026-09-20. Due for review every 3 months; expiry is reported by pnpm run check:freshness.