# opsinjs > A React design system for consumer- and patient-facing health apps. opsinjs is a design system for screens where somebody who is not a clinician reads their own health data, such as a blood-pressure reading, an HbA1c result or a symptom log, and has to decide what, if anything, to do about it. ALL 60 SPECIFIED COMPONENTS ARE IMPLEMENTED AND INSTALLABLE. They are: accordion, alert-banner, avatar, badge, body-map, button, callout, card, care-card, checkbox, combobox, consent-sheet, dialog, disclaimer-note, divider, dose-tracker, empty-state, field, goal-ring, icon-button, link, log-sheet, menu, metric-tile, number-field, popover, progress, questionnaire, radio-group, range-bar, range-legend, reading-input, relative-time, result-card, scale-input, score-dial, scroll-area, segmented-control, select, sheet, skeleton, slider, source-citation, spinner, status-pill, stepper, surface, switch, symptom-picker, tab-bar, table, tabs, term, textarea, timeline-entry, toast, tooltip, trend-sparkline, value, visually-hidden. Every id in the catalogue is implemented. The screen pages are specimens; most of them are not implemented either. Every opsinjs component has been audited against WCAG 2.2 AA by its own authors, in a static source pass and a rendered pass, with the findings fixed in the same change. That audit is author-run and is not an independent review, and no component has had a clinical review. `shipped` means the source installs and its accessibility was audited by the authors, and it does not mean an independent accessibility review or a clinical review has happened. Do not put one on a production health surface. The record of the audit is ADR 0025. Pages carry a machine-readable status, and `/r/index.json` carries `implemented` per id. Do not generate code against a proposed API and do not describe an unimplemented component as shipping. The tokens, the doctrine (health, accessibility, content, foundations) and the measured contrast figures are real today. Docs version 0.0.0. Corpus compiled 2026-09-22T04:14:10.533Z. 402 pages. ## Reading this site as a machine - Append `.md` to any documentation URL to get that page as processed markdown, with its frontmatter: imports stripped, headings with explicit ids, code and tables as markdown. Documentation components are NOT rendered to prose. For most of them the attributes are the content and the values behind them are published separately at `/r/index.json` and under Reference. - `` is the exception, and on a component page it is the element to read. It is a paired element, never self-closing, and the prose between its opening and closing tags is text an author wrote which survives into the `.md` twin word for word. That prose is where the page states whether the component has been reviewed. Every component page carries one, and every one of them says the source installs, has been audited against WCAG 2.2 AA by the authors rather than independently reviewed, and has had no clinical review. - [The whole corpus in one file](https://opsinjs.pensievelabs.org/llms-full.txt) is size-capped, and it names every page it had to drop. The shards below cover 8 of the 16 sections; Introduction, Start here, Recipes, Patterns, Handbook, Agents & automation, Registry & distribution, Project have no shard, so take those pages one at a time from the list further down this file. Every documentation URL answers to a `.md` suffix. - [Components and screens](https://opsinjs.pensievelabs.org/llms-components.txt) is one of those shards. Every component page and every screen specimen is here: the built components and the specifications, each carrying its own status. Read this before answering a question about what opsinjs provides. - [Health, accessibility and content doctrine](https://opsinjs.pensievelabs.org/llms-health.txt) is one of those shards. The rules that decide what a health interface may assert, how it must be operable, and how it must be worded. - [Foundations and theming](https://opsinjs.pensievelabs.org/llms-foundations.txt) is one of those shards. What each token means and how to change it. The generated list of every one is the reference shard. - [Generated reference](https://opsinjs.pensievelabs.org/llms-reference.txt) is one of those shards. Every token, CSS variable, measured contrast pair, defined term and exported type, generated from the same sources the build uses. - [The registry catalog](https://opsinjs.pensievelabs.org/r/registry.json) is the shadcn-spec catalog, and the file `npx shadcn@latest mcp` reads. - [The component roster](https://opsinjs.pensievelabs.org/r/index.json) covers every id opsinjs has claimed, its status, and whether anything is installable. This is the definitive answer to "does opsinjs have a …?". - [The offline bundle](https://opsinjs.pensievelabs.org/r/docs.json) is the same corpus as JSON, one record per page. - `GET /api/search?query=&tag=
` runs a full-text search. The parameter is `query`; `q` returns nothing. - `GET /r/.json` returns one registry item. Single-word aliases resolve: `modal` reaches `dialog`. Multi-word aliases are not slugs and have no URL of their own. `/r/gauge-bar.json` is a 404, so map a phrase to an id through the `aliases` field on the roster. ## Rules for generating against opsinjs - Never state that an opsinjs component exists without checking. 60 are implemented and named in the summary above; every other id is a specification. `implemented` on the roster row in https://opsinjs.pensievelabs.org/r/index.json is the authority, and code generated against a `planned` id is generated against a proposal. - Never invent a prop, a variant or a token name. The catalogue and the generated reference are the only authorities. - Never carry clinical status in a category colour, or category identity in a status colour. The two axes are separate and mixing them is the failure this system is built to prevent. - Never present a number without its unit and its precision rule, and never label a value "normal". ## Introduction What opsinjs is, who it is for, and the one claim it makes about health interfaces. - [Introduction](https://opsinjs.pensievelabs.org/): opsinjs is a React design system for consumer health apps. It is the components that show a person their own numbers, and the rules that keep them honest. (kind: guide · also known as: what is opsinjs, introduction to opsinjs, opsinjs overview) ## Start here Installation, the five-minute map of the site, and an honest fit checklist that says no to clinician-facing and regulated-device work. - [Start here](https://opsinjs.pensievelabs.org/start): A five-minute map of this site, and the shortest useful path through it for your role. (kind: guide · also known as: start here, five minute map, where do I begin) - [Add your first component](https://opsinjs.pensievelabs.org/start/add-your-first-component): One command, what it will put in your project, and nothing else to read. (kind: guide · also known as: add a component, one command install, copy in a component) - [Browser support](https://opsinjs.pensievelabs.org/start/browser-support): The tested floor, and the per-feature contract for what happens in a browser that lacks a progressive enhancement. (kind: guide · also known as: browser support, supported browsers, safari floor, progressive enhancement) - [FAQ](https://opsinjs.pensievelabs.org/start/faq): Twenty questions that would otherwise become issues, each answered at its own anchor. (kind: guide · also known as: faq, frequently asked questions, common questions) - [For designers](https://opsinjs.pensievelabs.org/start/for-designers): What opsinjs fixes, what it expects you to decide, and the handful of pages a designer actually needs. (kind: guide · also known as: for designers, designer onboarding, design handoff) - [Framework support](https://opsinjs.pensievelabs.org/start/framework-support): Which React setups opsinjs targets, what it requires of them, and where the server/client boundary falls. (kind: guide · also known as: framework support, supported frameworks, rsc support, server components) - [Installation](https://opsinjs.pensievelabs.org/start/installation): Which install path to take, what each one assumes, and the four things every path has to get right. (kind: guide · also known as: installation, install opsinjs, setup, getting set up) - [Astro](https://opsinjs.pensievelabs.org/start/installation/astro): React islands, per-island hydration, and why a health interface should think twice before shipping one. (kind: guide · also known as: astro install, astro islands opsinjs) - [components.json](https://opsinjs.pensievelabs.org/start/installation/components-json): Every field opsinjs reads, what it does, and the one entry you have to add by hand. (kind: guide · also known as: components.json, registry configuration, shadcn config, opsinjs namespace) - [Manual installation](https://opsinjs.pensievelabs.org/start/installation/manual): No CLI. You place the tokens, the utility, and one component by hand, so you can see exactly what lands. (kind: guide · also known as: manual install, install without the cli, no cli install) - [Monorepo](https://opsinjs.pensievelabs.org/start/installation/monorepo): Workspaces, aliases and the @source lines Tailwind needs when the app is not the repository root. (kind: guide · also known as: monorepo install, workspaces setup, source lines, shared ui package) - [Next.js](https://opsinjs.pensievelabs.org/start/installation/next): The reference install. App Router, Tailwind v4, the exact CSS import position, and where the theme class belongs. (kind: guide · also known as: next.js install, app router setup, nextjs opsinjs) - [React Router](https://opsinjs.pensievelabs.org/start/installation/react-router): The framework-mode install. Server rendering, route modules, and where the stylesheet goes. (kind: guide · also known as: react router install, remix opsinjs, framework mode) - [TanStack Start](https://opsinjs.pensievelabs.org/start/installation/tanstack-start): The intended install path, and the parts that are specified rather than tested. (kind: guide · also known as: tanstack start install, tanstack router opsinjs) - [Upgrading](https://opsinjs.pensievelabs.org/start/installation/upgrading): Taking updates on code you own. Diffs, dry runs, three-way merges, and how to know which version you started from. (kind: guide · also known as: upgrading opsinjs, taking updates, diff copied source) - [Vite](https://opsinjs.pensievelabs.org/start/installation/vite): The client-only install, and the source-scanning gotcha that bites hardest here. (kind: guide · also known as: vite install, vite react opsinjs) - [Is opsinjs right for this project?](https://opsinjs.pensievelabs.org/start/is-opsinjs-right): An honest fit checklist that will tell you no. It names the three kinds of product opsinjs actively refuses to serve. (kind: guide · also known as: is opsinjs right, fit check, should I use opsinjs, non-goals) - [Quick start](https://opsinjs.pensievelabs.org/start/quick-start): Build a result card that shows one value, its reference range and its clinical status, from three components that are implemented and installable. (kind: guide · also known as: quick start, first result card, hello world) - [Reading these docs](https://opsinjs.pensievelabs.org/start/reading-these-docs): The page contracts, the status vocabulary, and how to read a token or contrast table without being misled by it. (kind: guide · also known as: how to read these docs, page contracts, status badges, docs conventions) - [Safety, scope and limitations](https://opsinjs.pensievelabs.org/start/safety-scope-and-limitations): opsinjs is a user-interface system. It is not a medical device, it makes no clinical decisions, and adopting it changes none of your regulatory obligations. (kind: health · evidence: cited · also known as: not a medical device, scope of opsinjs, limitations of opsinjs, what opsinjs is not) - [Troubleshooting](https://opsinjs.pensievelabs.org/start/troubleshooting): The failures that actually happen, each with its symptom, its cause and its fix, plus an honest note about the ones whose exact error text we have not seen yet. (kind: guide · also known as: troubleshooting, common errors, it does not work, unstyled components) ## Recipes Task-first pages: the components, tokens and copy rules for one job, in one scroll. - [Recipes](https://opsinjs.pensievelabs.org/recipes): Task-first builds gather the components, tokens, copy and safety checks for one job into one scroll. (kind: guide) - [Choose a component](https://opsinjs.pensievelabs.org/recipes/choose-a-component): Start from the data you have and end with the component that may honestly display it. (kind: recipe · evidence: opinion) - [Ask for consent before collecting](https://opsinjs.pensievelabs.org/recipes/consent-before-collection): Ask for one category of health data at the moment it becomes useful, in words the reader can act on, with declining as easy as agreeing. (kind: recipe · evidence: opinion) - [Capture a daily log entry](https://opsinjs.pensievelabs.org/recipes/daily-log-entry): Record a measurement in three taps, one-handed, without leaving the screen the person was already on. (kind: recipe · evidence: opinion) - [Build a health metric card](https://opsinjs.pensievelabs.org/recipes/health-metric-card): One measurement on a dashboard, with its unit, its age, its category and an honest answer in all five data states. (kind: recipe · evidence: opinion) - [Escalate an alert without alarming](https://opsinjs.pensievelabs.org/recipes/staged-alert): Move a message up the escalation ladder only as far as it has earned, and spend the screen's alarm budget on the one thing that deserves it. (kind: recipe · evidence: opinion) - [Show a trend with an honest caption](https://opsinjs.pensievelabs.org/recipes/trend-with-a-caption): Draw change over time and write the sentence beneath it, with the direction of the change separated from whether it is good news. (kind: recipe · evidence: opinion) - [Show a value against a reference range](https://opsinjs.pensievelabs.org/recipes/value-against-a-range): Put one measurement next to the range it is compared with, without implying a diagnosis, a verdict or a target. (kind: recipe · evidence: mixed) ## Components Every component opsinjs has claimed, in one list. Some have real source behind them and install from /r/.json; the rest are specifications. A specification page states intent, when not to use it, the clinical contract, the API and the accessibility bar. Each entry's `status`, and `implemented` in /r/index.json, say which kind you are reading. - [Components](https://opsinjs.pensievelabs.org/components): Every component opsinjs has specified, with the status of each, listed in one table so nobody has to guess whether something exists. (kind: reference) - [Accordion](https://opsinjs.pensievelabs.org/components/accordion): Sections that expand and collapse, one or several at a time, built on Base UI Accordion. (kind: component · status: shipped · also known as: disclosure, expander, collapsible) - [AlertBanner](https://opsinjs.pensievelabs.org/components/alert-banner): A message that appears at the top of a screen because something needs your attention now, saying what has happened and what to do about it. (kind: component · status: shipped · also known as: warning, notification, alert, banner, warning banner, notification banner, inline alert) - [Anatomy of a component page](https://opsinjs.pensievelabs.org/components/anatomy-of-a-component-page): The fourteen sections a shipped component page may carry, the eight it must, and the word budget it fits inside. (kind: handbook · also known as: page contract, page template, lean component page, documentation structure) - [Avatar](https://opsinjs.pensievelabs.org/components/avatar): A picture or initials standing for a person, with the person's name as its accessible label and a neutral fallback when there is no picture. (kind: component · status: shipped · also known as: profile picture, initials, user image) - [Badge](https://opsinjs.pensievelabs.org/components/badge): A small neutral label attached to something else, such as a count on a tab or a word on a list row. It takes neither colour axis and never stands in for status. (kind: component · status: shipped · also known as: counter, label chip) - [BodyMap](https://opsinjs.pensievelabs.org/components/body-map): A neutral, non-realistic body schematic for pointing at where something is. It records region keys and interprets nothing, so the product owns every meaning. (kind: component · status: shipped · also known as: pain map, anatomy diagram, where does it hurt) - [Button](https://opsinjs.pensievelabs.org/components/button): A control you press to make something happen. It is the least clinical component here, and its page sets the pattern every other component page follows. (kind: component · status: shipped · also known as: cta, action, submit, primary button) - [Callout](https://opsinjs.pensievelabs.org/components/callout): A short piece of set-apart information that helps you understand what you are reading without claiming anything about your health. A note, a tip or a caveat. (kind: component · status: shipped · also known as: admonition, note, info box, aside, note box, tip) - [Card](https://opsinjs.pensievelabs.org/components/card): A bounded group of related content with a border and consistent padding is the ordinary box that most of a screen is made of. (kind: component · status: shipped · also known as: panel, container, box, tile group, content box) - [CareCard](https://opsinjs.pensievelabs.org/components/care-card): A card that tells you what to do and when. It carries one instruction at one of three levels of urgency, with the urgency stated in the heading, not implied. (kind: component · status: shipped · also known as: next steps, what to do, advice, action card, what to do next, advice card, guidance card) - [Checkbox](https://opsinjs.pensievelabs.org/components/checkbox): A single labelled box a reader ticks, unticks or leaves in a mixed state, built on Base UI Checkbox and carrying neither colour axis. (kind: component · status: shipped · also known as: tick box, multi select) - [Combobox](https://opsinjs.pensievelabs.org/components/combobox): A text input that narrows a list the product supplies as the reader types, then lets them choose one match. (kind: component · status: shipped · also known as: autocomplete, typeahead, search select) - [ConsentSheet](https://opsinjs.pensievelabs.org/components/consent-sheet): A sheet that asks permission for one specific thing at a time, explains what it is for, and makes saying no or changing your mind as easy as saying yes. (kind: component · status: shipped · also known as: consent, permission, opt in, data sharing, agree) - [Dialog](https://opsinjs.pensievelabs.org/components/dialog): A window that opens over the page and waits for an answer. It takes your keyboard and attention until you deal with it, and gives them back where it found them. (kind: component · status: shipped · also known as: modal, alert dialog, popup, confirm) - [DisclaimerNote](https://opsinjs.pensievelabs.org/components/disclaimer-note): The short standing note saying this is information, not medical advice. It is placed by rule, so it is always in the same place and never in the way. (kind: component · status: shipped · also known as: not medical advice, disclaimer, legal note, safety note, small print) - [Divider](https://opsinjs.pensievelabs.org/components/divider): A thin line that separates two groups of content, with an optional centred label, drawn as a neutral hairline and carrying no status or category colour. (kind: component · status: shipped · also known as: separator, rule) - [DoseTracker](https://opsinjs.pensievelabs.org/components/dose-tracker): A record of the medicine doses a product has already logged, drawing each as a fact with a word and a shape, never computing adherence or judging a missed dose. (kind: component · status: shipped · also known as: medication, pill tracker, dose, adherence tracker) - [EmptyState](https://opsinjs.pensievelabs.org/components/empty-state): What a screen shows before there is anything on it. It says plainly why it is empty and gives you one clear thing to do about it. (kind: component · status: shipped · also known as: blank slate, no data, nothing here, zero state) - [Field](https://opsinjs.pensievelabs.org/components/field): The wrapper that gives every input a visible label, a hint, an error message and the wiring between them. It is why no control here can ship without a name. (kind: component · status: shipped · also known as: form field, label, input wrapper, error message, hint, form control, validation message) - [GoalRing](https://opsinjs.pensievelabs.org/components/goal-ring): A ring that shows how far a reading has come towards a goal the product set, paired with a text twin that states every figure, and rewarding no streak. (kind: component · status: shipped · also known as: activity ring, close your rings, daily goal) - [IconButton](https://opsinjs.pensievelabs.org/components/icon-button): A button whose only visible content is an icon, so it always requires an accessible name you supply. Prefer a labelled button wherever there is room for a word. (kind: component · status: shipped · also known as: glyph button, round button) - [Link](https://opsinjs.pensievelabs.org/components/link): The control that takes the reader somewhere else, and the one place the system decides how a navigation link looks, so a banner's action and a card's match. (kind: component · status: shipped · also known as: anchor, hyperlink) - [LogSheet](https://opsinjs.pensievelabs.org/components/log-sheet): A small sheet that slides up so you can record something in a few seconds without leaving the screen you were on. One reading, one dose, one note. (kind: component · status: shipped · also known as: log, capture, quick entry, bottom sheet entry, diary, journal, daily entry) - [Menu](https://opsinjs.pensievelabs.org/components/menu): A list of actions opened from a button, built on Base UI Menu, that draws neutral chrome and keeps every safety-relevant action out on the screen. (kind: component · status: shipped · also known as: dropdown menu, context menu, overflow menu) - [MetricTile](https://opsinjs.pensievelabs.org/components/metric-tile): A compact readout of one measurement. It carries the number, its unit and how recent it is, and it is sized to sit in a grid with several others. (kind: component · status: shipped · also known as: stat, kpi, tile, vitals, resting heart rate, spo2, summary tile, steps) - [NumberField](https://opsinjs.pensievelabs.org/components/number-field): An input for a non-clinical number with increment and decrement steppers, built on Base UI NumberField. (kind: component · status: shipped · also known as: stepper input, quantity input) - [Popover](https://opsinjs.pensievelabs.org/components/popover): A small panel anchored to the control that opened it, floated in a portal and dismissed by leaving it, built as a thin themed wrapper over Base UI Popover. (kind: component · status: shipped · also known as: anchored panel, flyout) - [Progress](https://opsinjs.pensievelabs.org/components/progress): A bar for how far through a task or a set of steps the reader has got, built on Base UI Progress and never used to draw a health value. (kind: component · status: shipped · also known as: progress bar, completion) - [Questionnaire](https://opsinjs.pensievelabs.org/components/questionnaire): The styled form shell that groups a product's own questions and shows how far through them a reader is, while scoring and interpreting nothing clinical. (kind: component · status: shipped · also known as: survey, assessment, phq, screening form) - [RadioGroup](https://opsinjs.pensievelabs.org/components/radio-group): A vertical list of labelled options where exactly one can be chosen, kept to a single tab stop with a roving focus. (kind: component · status: shipped · also known as: radio buttons, single choice) - [RangeBar](https://opsinjs.pensievelabs.org/components/range-bar): A single measurement drawn on a line, so you can see at a glance where your number sits compared with the range it is usually expected to fall in. (kind: component · status: shipped · also known as: reference range, normal range, in range, range indicator, gauge bar) - [RangeLegend](https://opsinjs.pensievelabs.org/components/range-legend): The key that names the tones a RangeBar draws, so a reader learns in one place what the reference band and each status colour mean. It asserts nothing itself. (kind: component · status: shipped · also known as: key, chart legend, band legend) - [ReadingInput](https://opsinjs.pensievelabs.org/components/reading-input): A field for typing in a measurement, with the unit shown and switchable beside the number, and room for an advisory the product wrote. (kind: component · status: shipped · also known as: measurement input, numeric input, unit switch, enter a reading, numeric entry, manual entry) - [RelativeTime](https://opsinjs.pensievelabs.org/components/relative-time): When something happened, written the way people say it. The exact date and time stay in reach, and explicit words appear once the staleness boundary is passed. (kind: component · status: shipped · also known as: ago, timestamp, last updated, freshness, staleness, time ago, date display) - [ResultCard](https://opsinjs.pensievelabs.org/components/result-card): One test result, shown in full. What was measured, the number, where it sits against its range, what that means in plain English, and what to do next. (kind: component · status: shipped · also known as: results, lab result, test result, report card, blood pressure, a1c) - [ScaleInput](https://opsinjs.pensievelabs.org/components/scale-input): A rating scale drawn from the points and end words the product supplies, for a self-report the product reads, shipping no instrument of its own. (kind: component · status: shipped · also known as: pain scale, rating scale, likert) - [ScoreDial](https://opsinjs.pensievelabs.org/components/score-dial): A single composite score shown on a dial with its band named in words, alongside an honest statement of what went into the number. (kind: component · status: shipped · also known as: gauge, dial, ring, score, index, bmi) - [ScrollArea](https://opsinjs.pensievelabs.org/components/scroll-area): A bounded scrolling region with a thin neutral scrollbar that keeps a card or panel's overflow reachable without replacing the page's own native scroll. (kind: component · status: shipped · also known as: scroller, overflow container) - [SegmentedControl](https://opsinjs.pensievelabs.org/components/segmented-control): A row of mutually exclusive options with exactly one chosen at a time, for switching a single view between a small set of windows. (kind: component · status: shipped · also known as: segmented buttons, toggle group) - [Select](https://opsinjs.pensievelabs.org/components/select): A trigger that opens a floating list to choose one option from, built on Base UI Select and drawing only neutral chrome. (kind: component · status: shipped · also known as: dropdown, picker) - [Sheet](https://opsinjs.pensievelabs.org/components/sheet): A panel that slides up from the bottom, stops at sensible heights, and can be dragged or dismissed. The one-handed way to act without leaving the page. (kind: component · status: shipped · also known as: drawer, bottom sheet, modal sheet, detent, side panel, slide over) - [Skeleton](https://opsinjs.pensievelabs.org/components/skeleton): A grey placeholder in the shape of the content that is loading, so the page does not jump when it arrives. It is never in the shape of a number. (kind: component · status: shipped · also known as: loading placeholder, shimmer, loading state, placeholder, ghost) - [Slider](https://opsinjs.pensievelabs.org/components/slider): A single coarse, non-clinical preference set by dragging a thumb along a track, and never a clinical reading or a precise measurement. (kind: component · status: shipped · also known as: range input, drag to set) - [SourceCitation](https://opsinjs.pensievelabs.org/components/source-citation): Where a piece of health information came from, in plain words, with an optional link to the fuller citation and an optional date it was last checked. (kind: component · status: shipped · also known as: citation, evidence link, reviewed by) - [Spinner](https://opsinjs.pensievelabs.org/components/spinner): An indeterminate loading ring for a brief in-place wait whose shape is unknown, reached for only where a skeleton cannot say what is arriving. (kind: component · status: shipped · also known as: loader, busy indicator, activity indicator) - [StatusPill](https://opsinjs.pensievelabs.org/components/status-pill): A short label that says which of four levels of attention something needs. It is shown as a word, an icon and a colour together, never as a colour alone. (kind: component · status: shipped · also known as: chip, status chip, status badge, status label, traffic light) - [Stepper](https://opsinjs.pensievelabs.org/components/stepper): Progress through a sequence of steps, drawn as a read-only indicator showing which steps are complete, which one is current, and which are still to come. (kind: component · status: shipped · also known as: wizard, step indicator, multi step) - [Surface](https://opsinjs.pensievelabs.org/components/surface): The primitive behind every panel, sheet and card. It decides how solid or translucent a layer looks, and guarantees that whatever sits on it stays readable. (kind: component · status: shipped · also known as: material, blur, translucency, glass, vibrancy, elevation, layer) - [Switch](https://opsinjs.pensievelabs.org/components/switch): A labelled on-or-off control that commits the moment it is flipped, for a single setting rather than a form value submitted later. (kind: component · status: shipped · also known as: toggle) - [SymptomPicker](https://opsinjs.pensievelabs.org/components/symptom-picker): A multi-select over a symptom list the product supplies, recording which options a reader ticks and never checking, triaging or interpreting them. (kind: component · status: shipped · also known as: symptoms, how are you feeling, symptom checker) - [TabBar](https://opsinjs.pensievelabs.org/components/tab-bar): The persistent bar of top-level destinations at the foot of a phone screen, marking one as current with a heavier label and a top indicator rather than colour. (kind: component · status: shipped · also known as: bottom navigation, nav bar) - [Table](https://opsinjs.pensievelabs.org/components/table): Rows and columns in a real semantic table, the readable twin a chart ships beside it, with a required caption, right-aligned numeric columns and its own scroll. (kind: component · status: shipped · also known as: data table, grid, rows and columns) - [Tabs](https://opsinjs.pensievelabs.org/components/tabs): A row of tabs that switches between panels sharing one region. The list is one tab stop with a roving focus, and choosing a tab swaps the panel. (kind: component · status: shipped · also known as: tab list, view switcher) - [Term](https://opsinjs.pensievelabs.org/components/term): A clinical word shown with its everyday meaning attached, so you can read a sentence without having to look anything up. (kind: component · status: shipped · also known as: glossary term, jargon, plain english, definition, tooltip term, plain word) - [Textarea](https://opsinjs.pensievelabs.org/components/textarea): A multi-line box for a free-text note, a native textarea wearing the opsinjs tokens rather than a Base UI primitive, that takes neither colour axis. (kind: component · status: shipped · also known as: long text, notes input) - [TimelineEntry](https://opsinjs.pensievelabs.org/components/timeline-entry): One dated event in a vertical history, with a neutral rail and marker, the time written the way people say it, and any clinical status shown as a nested pill. (kind: component · status: shipped · also known as: history item, event list, activity feed) - [Toast](https://opsinjs.pensievelabs.org/components/toast): A brief, self-dismissing confirmation of the reader's own action, built on Base UI Toast. (kind: component · status: shipped · also known as: snackbar, transient message, notification toast) - [Tooltip](https://opsinjs.pensievelabs.org/components/tooltip): A short supplementary label that appears when a pointer rests on a control or a keyboard moves focus to it, for information a reader can do without. (kind: component · status: shipped · also known as: hover label) - [TrendSparkline](https://opsinjs.pensievelabs.org/components/trend-sparkline): A small line showing how one measurement has moved over time, with a caption that says what changed and leaves the verdict to you. (kind: component · status: shipped · also known as: chart, graph, sparkline, over time, trend, mini chart, line chart) - [Value](https://opsinjs.pensievelabs.org/components/value): A number and its unit, formatted the same way everywhere. It is rounded honestly, spoken correctly, and never shown to more precision than the measurement has. (kind: component · status: shipped · also known as: number, unit, format, formatted number, format a number, numeric display, figure) - [VisuallyHidden](https://opsinjs.pensievelabs.org/components/visually-hidden): Content that screen readers announce and eyes do not see. (kind: component · status: shipped · also known as: sr only, screen reader only, clip) ## Screens Whole-screen specimens showing the two colour axes, the material ladder and motion working together rather than in isolation. - [Screens](https://opsinjs.pensievelabs.org/screens): Whole composed surfaces, specified as units. This is where a correct component and a wrong page order still produce an unusable result. (kind: guide) - [Consent flow](https://opsinjs.pensievelabs.org/screens/consent-flow): A short sequence that asks for one scope at a time, records what was agreed to, and makes declining as easy as agreeing. (kind: screen · evidence: opinion) - [Daily log screen](https://opsinjs.pensievelabs.org/screens/daily-log-screen): The surface somebody returns to every day, judged on how little it costs rather than on how much it shows. (kind: screen · evidence: opinion) - [Diabetes medicines app](https://opsinjs.pensievelabs.org/screens/diabetes-medicines-app): A whole single-page app assembled only from opsinjs parts. It records the medicines somebody takes, reminds them, and refuses to do anything else. (kind: screen · evidence: mixed · also known as: medicines app, dose reminder, medication tracker, medicines diary, dose diary) - [Onboarding screen](https://opsinjs.pensievelabs.org/screens/onboarding-screen): The first run collects the smallest amount before something genuinely useful is on the screen. (kind: screen · evidence: opinion) - [Results screen](https://opsinjs.pensievelabs.org/screens/results-screen): One result, what it means and what happens next. Read in that order, by eye and by screen reader. (kind: screen · evidence: opinion) - [Trends screen](https://opsinjs.pensievelabs.org/screens/trends-screen): Change over time across several metrics, with stated windows, honest axes and a text equivalent for every chart. (kind: screen · evidence: opinion) ## Health The doctrine layer: clinical status semantics, reference ranges, numbers and units, alarm fatigue, consent, uncertainty. Real today, and independent of any component. - [Overview](https://opsinjs.pensievelabs.org/health): What makes opsinjs a health design system rather than a general-purpose component library, and which decisions it fixes on a product's behalf. (kind: health · evidence: opinion · also known as: health design system, clinical safety, patient-facing, consumer health) - [Alarm fatigue](https://opsinjs.pensievelabs.org/health/alarm-fatigue): Escalation is budgeted rather than judged screen by screen. This page sets the ceiling, names who owns it, and says what an interface loses by overspending it. (kind: health · evidence: mixed · also known as: alert fatigue, escalation budget, too many alerts, notification fatigue, desensitisation) - [Category identity](https://opsinjs.pensievelabs.org/health/category-identity): The six metric families, the four roles each one exposes, and the meanings a category colour is forbidden to carry. (kind: health · evidence: opinion · also known as: category colour, metric category, heart colour, sleep colour, metric family) - [Clinical interaction guidelines](https://opsinjs.pensievelabs.org/health/clinical-interaction-guidelines): Ten rules for any interface that shows someone their own health data. Each rule is written as a prohibition a reviewer can test against a rendered screen. (kind: health · evidence: mixed · also known as: clinical rules, prohibitions, safety rules, ten rules, health ui rules) - [Clinical status semantics](https://opsinjs.pensievelabs.org/health/clinical-status-semantics): The four status levels steady, watch, attention and urgent. Each has a fixed meaning, a fixed tone, a named threshold owner, and meanings it is never read as. (kind: health · evidence: mixed · also known as: severity, urgency, triage, status levels, steady watch attention urgent) - [Consent and disclosure](https://opsinjs.pensievelabs.org/health/consent-and-disclosure): Consent that is granular, revocable, recorded and re-asked, and the difference between a lawful basis for processing and a person's actual understanding. (kind: health · evidence: mixed · also known as: withdraw consent, privacy notice) - [Crisis and self-harm](https://opsinjs.pensievelabs.org/health/crisis-and-self-harm): What an interface must do when someone discloses thoughts of suicide or self-harm, and how to signpost support without ambush, judgement or a dead end. (kind: health · evidence: opinion · also known as: self-harm, suicide, crisis line, safeguarding, distress, mental health crisis) - [Data provenance and device accuracy](https://opsinjs.pensievelabs.org/health/data-provenance-and-device-accuracy): Who measured a value, with what instrument, by what method and when, and the strict limit on what an interface may assert about a number it cannot vouch for. (kind: health · evidence: opinion · also known as: provenance, device accuracy, who measured, wearable, source of data, self-reported) - [Delivering difficult results](https://opsinjs.pensievelabs.org/health/delivering-difficult-results): Tone, sequence and structure for the moment an app tells someone something they did not want to hear, with no clinician present and no question available. (kind: health · evidence: opinion · also known as: bad news, tone, difficult result, abnormal result wording, breaking bad news) - [Emergency and escalation](https://opsinjs.pensievelabs.org/health/emergency-and-escalation): What an interface must do when a value may mean someone needs help today. The one path in the system that outranks every other rule, budget and preference. (kind: health · evidence: opinion · also known as: emergency, call an ambulance, escalation, red flag, urgent care, 999, 911) - [Evidence and references](https://opsinjs.pensievelabs.org/health/evidence-and-references): Every source this pillar rests on, what each one supports, and a register recording which pages carry evidence and which carry argument. (kind: health · evidence: mixed · also known as: references, bibliography, citations, sources, evidence discipline) - [Motion in health UI](https://opsinjs.pensievelabs.org/health/motion-in-health-ui): Motion may confirm an action, orient a reader and soften a transition. It may never carry urgency, meaning or a value, because a reader can miss it entirely. (kind: health · evidence: mixed · also known as: animation, pulsing, flashing, blinking, urgency motion, calm motion) - [Notifications and off-screen alerts](https://opsinjs.pensievelabs.org/health/notifications-and-off-screen-alerts): A push notification is a clinical statement delivered to a lock screen the product does not control, in front of people the reader did not choose. (kind: health · evidence: opinion · also known as: push notification, lock screen, badge count, off screen, quiet hours, widget) - [Numbers, units and precision](https://opsinjs.pensievelabs.org/health/numbers-units-precision): The canonical rules for rendering a health number, covering digits, units, zero and rounding. Rounding is a truth claim here, not a formatting preference. (kind: health · evidence: mixed · also known as: rounding, significant figures, decimals, decimal places, number formatting) - [On-screen privacy](https://opsinjs.pensievelabs.org/health/on-screen-privacy): Health data is read on trains, in offices and over shoulders. The page sets how much of it an interface exposes to the room around the reader. (kind: health · evidence: opinion · also known as: shoulder surfing, hide values, screenshot, privacy screen, app switcher) - [Reference ranges](https://opsinjs.pensievelabs.org/health/reference-ranges): How to show a value against a range without implying a diagnosis, and why the word "normal" is banned from every user-facing string about a person's own result. (kind: health · evidence: mixed · also known as: normal, abnormal, out of range, healthy range, cut-off, reference interval) - [Regulatory context](https://opsinjs.pensievelabs.org/health/regulatory-context): A starting map of the regimes that may apply to a consumer health product, what each one asks of the product, and the large amount opsinjs does not contribute. (kind: health · evidence: mixed · also known as: DCB0129, DCB0160, MDR, SaMD, FDA, CE mark, UKCA, regulation, compliance) - [Risk and statistics](https://opsinjs.pensievelabs.org/health/risk-and-statistics): Absolute risk before relative risk, natural frequencies before percentages, and no probability without the population it came from and the window it covers. (kind: health · evidence: opinion · also known as: absolute risk, relative risk, natural frequencies, probability, odds, percentage) - [Safety review checklist](https://opsinjs.pensievelabs.org/health/safety-review-checklist): A printable pre-ship checklist for any screen that displays, interprets or collects health information. Each item names the rule it enforces. (kind: health · evidence: opinion · also known as: pre-ship checklist, safety review, sign off, clinical review, launch checklist) - [Trends and change](https://opsinjs.pensievelabs.org/health/trends-and-change): Direction is a fact and valence is a judgement. Each metric declares the minimum window a series needs before an interface may draw a trend through it. (kind: health · evidence: opinion · also known as: direction of change, improving, worsening, delta) - [The two colour axes](https://opsinjs.pensievelabs.org/health/two-colour-axes): Category identity and clinical status are two independent colour channels. No colour value may carry both, and no element may be tinted by both axes at once. (kind: health · evidence: mixed · also known as: two axes, category vs status, colour axes, never mix colour) - [Uncertainty, staleness and missing data](https://opsinjs.pensievelabs.org/health/uncertainty-and-staleness): How to render an estimate, an old reading, a partial sync and an outright absence so that a reader can tell each of them apart from a fresh measurement. (kind: health · evidence: opinion · also known as: stale data, estimated, missing data, unknown) - [Unit systems](https://opsinjs.pensievelabs.org/health/unit-systems): mmol/L against mg/dL, kilograms against stones and pounds, Celsius against Fahrenheit. Conversion is where a wrong answer is a plausible number, not an error. (kind: health · evidence: opinion · also known as: mmol/L, mg/dL, imperial, metric, stone, fahrenheit, unit conversion) - [Who this is for](https://opsinjs.pensievelabs.org/health/who-this-is-for): The reader of a consumer health screen is anxious, distracted, on a phone, and has not seen the unit before. Every rule in this section follows from that. (kind: health · evidence: opinion · also known as: layperson, numeracy, reading age, patient audience, non-clinician) ## Foundations What a token means in colour, materials, motion, typography, shape, space, data states and data visualisation. - [Foundations](https://opsinjs.pensievelabs.org/foundations): The ten token families and six system-wide contracts that every opsinjs component is obliged to obey, and what each one decides on your behalf. (kind: foundation) - [Colour](https://opsinjs.pensievelabs.org/foundations/colour): How opsinjs decides what colour anything is. Two independent axes, one derivation engine, and a contrast floor the build refuses to ship below. (kind: foundation · also known as: colour system, color system, palette, oklch, ramp, hue, chroma) - [Colour blindness](https://opsinjs.pensievelabs.org/foundations/colour/colour-blindness): The status axis uses the worst possible hue family for colour vision deficiency, on purpose, and pays for it with a word, a shape and a generated audit. (kind: foundation · also known as: colour vision deficiency, color blind, deuteranopia, protanopia, tritanopia, greyscale legibility, red green) - [Colour roles](https://opsinjs.pensievelabs.org/foundations/colour/colour-roles): The four roles every colour token plays are surface, line, ink and accent. A contrast guarantee attaches to a pair, never to a colour. (kind: foundation · also known as: surface line ink, semantic colour, token naming, measured pair, role tokens) - [Contrast and APCA](https://opsinjs.pensievelabs.org/foundations/colour/contrast-and-apca): Both contrast models side by side. WCAG 2.2 is the conformance obligation, APCA the design tool, and this page states the floor the system will not ship below. (kind: foundation · also known as: APCA, Lc, WCAG, contrast ratio, 4.5:1, readability, luminance) - [Dark mode](https://opsinjs.pensievelabs.org/foundations/colour/dark-mode): Dark is re-derived from the same ladder rather than inverted, and there are seven invariants it has to preserve on the way. (kind: foundation · also known as: dark mode derivation, light first, colour scheme, night mode, inversion) - [Deriving a theme from your brand](https://opsinjs.pensievelabs.org/foundations/colour/deriving-a-theme): The one-colour workflow, what the engine does with your brand colour, and the six brand colours that make it argue with you. (kind: foundation · also known as: brand colour, brand color, white label, custom theme, one colour workflow) - [Gamut and Display-P3](https://opsinjs.pensievelabs.org/foundations/colour/gamut-and-p3): sRGB is the baseline, Display-P3 is a chroma escalation behind a media query, and the guard has to be a media query rather than a feature query. (kind: foundation · also known as: display-p3, wide gamut, srgb, color-gamut, gamut mapping, out of gamut) - [How the engine works](https://opsinjs.pensievelabs.org/foundations/colour/how-the-engine-works): The eight stages between one brand colour and an emitted, gamut-clamped, contrast-validated set of custom properties. (kind: foundation · also known as: derive theme, colour engine, lightness ladder, chroma clamp, apca loop, generate palette) - [Colour tokens](https://opsinjs.pensievelabs.org/foundations/colour/tokens): The generated reference for every colour token. It carries the naming grammar, both themes, both gamuts, and the measured pair each one belongs to. (kind: foundation · also known as: colour tokens, color tokens, css variables colour, opsin-status, opsin-category) - [Data states](https://opsinjs.pensievelabs.org/foundations/data-states): Empty, loading, error, stale and partial are the five states every data-bearing surface must render, so "we do not know" is never drawn as an ordinary reading. (kind: foundation · also known as: five data states, partial data, unknown value, missing value) - [Data visualisation](https://opsinjs.pensievelabs.org/foundations/data-visualisation): Charts are three things at once. A foundation with rules, a component family, and an accessibility surface that fails more often than any other. (kind: foundation · also known as: charts, graphs, visualisation) - [Accessible charts](https://opsinjs.pensievelabs.org/foundations/data-visualisation/accessible-charts): The table twin every chart ships with, the generated one-sentence summary, and the markup that stops a chart being an image full of numbers nobody can read. (kind: foundation · also known as: chart accessibility, data table twin, chart alt text, chart summary) - [Chart anatomy](https://opsinjs.pensievelabs.org/foundations/data-visualisation/chart-anatomy): Axes, ticks, bands and gaps. The rule against a truncated health y-axis, why the scale is fixed rather than fitted, and what a missing reading must look like. (kind: foundation · also known as: y-axis, axis truncation, gridlines, chart baseline) - [Chart colour](https://opsinjs.pensievelabs.org/foundations/data-visualisation/chart-colour): Sequential, diverging and qualitative ramps, why the category and status palettes are both unavailable to a chart series, and how a reference band is coloured. (kind: foundation · also known as: chart palette, sequential ramp, diverging ramp, qualitative ramp) - [Iconography](https://opsinjs.pensievelabs.org/foundations/iconography): One icon library, roles rather than filenames, and the rule that an icon never carries status on its own in a system whose category axis is glyph-driven. (kind: foundation · also known as: icons, lucide, icon library) - [Health glyphs](https://opsinjs.pensievelabs.org/foundations/iconography/health-glyphs): The medical symbols opsinjs will not use, because an app that borrows the visual language of clinical authority is claiming something it has not earned. (kind: foundation · also known as: medical icons, caduceus, stethoscope, cross symbol) - [Icon inventory](https://opsinjs.pensievelabs.org/foundations/iconography/icon-inventory): The generated list of every semantic icon role in the system and the lucide glyph it currently resolves to, so a swap is one mapping rather than a search. (kind: foundation · also known as: icon list, icon roles, available icons) - [Sizing and alignment](https://opsinjs.pensievelabs.org/foundations/iconography/sizing-and-alignment): Icons sized in em beside text and in fixed steps when standalone, optically aligned rather than box-aligned, and always separated from their touch target. (kind: foundation · also known as: icon size, optical alignment, icon stroke weight) - [Imagery](https://opsinjs.pensievelabs.org/foundations/imagery): Why an image in a health product is never neutral, the four kinds opsinjs recognises, and why the right number of pictures on a results screen is zero. (kind: foundation · also known as: images, pictures, visual assets) - [Avatars and identity](https://opsinjs.pensievelabs.org/foundations/imagery/avatars-and-identity): The smallest images in the product, and the ones most likely to assign an identity nobody chose. Defaults, initials, and why a silhouette is not neutral. (kind: foundation · also known as: initials avatar, identity image, default avatar) - [Body diagrams](https://opsinjs.pensievelabs.org/foundations/imagery/body-diagrams): The highest-stakes image in a health product. Drawing a body somebody can locate themselves on, solving the left-and-right problem, and implying no diagnosis. (kind: foundation · also known as: pain location diagram, body outline) - [Illustration style](https://opsinjs.pensievelabs.org/foundations/imagery/illustration-style): Where a drawing is the right medium, the constraints that keep an illustration honest, and why a friendly-tech-company house style is wrong for a health result. (kind: foundation · also known as: illustration, drawing style, spot illustration) - [Photography](https://opsinjs.pensievelabs.org/foundations/imagery/photography): The narrow set of places a photograph belongs in a health product, the stock-photography failure mode, and the consent questions a design system cannot answer. (kind: foundation · also known as: photos, stock photography, image selection) - [Skin-tone representation](https://opsinjs.pensievelabs.org/foundations/imagery/skin-tone-representation): Why the range of skin tones in a health product's imagery is a correctness requirement, not a style preference, and what a set must cover before it ships. (kind: foundation · also known as: skin tone, representation, diverse imagery, equity in imagery) - [Interaction states](https://opsinjs.pensievelabs.org/foundations/interaction-states): How hover, press, focus, disabled, selected and loading are derived in OKLCH from a single role, so every component reacts identically without a second colour. (kind: foundation · also known as: hover, pressed, focus-visible, disabled state, selected state) - [Layering and elevation](https://opsinjs.pensievelabs.org/foundations/layering-and-elevation): The fixed stacking order every overlay, sheet, popover and toast belongs to, and the health rule that nothing may ever cover the value it is talking about. (kind: foundation · also known as: z-index, stacking order, portal layer, overlay order) - [Layout](https://opsinjs.pensievelabs.org/foundations/layout): The page shell, the safe-area and keyboard contract, and the two screen shapes that between them cover almost every consumer health surface. (kind: foundation · also known as: page shell, safe area, app shell, thumb zone) - [Materials](https://opsinjs.pensievelabs.org/foundations/materials): Six ordered rungs answer what a surface is made of and what is behind it. Each rung has a stated job, an opaque fallback and a contrast floor it has to clear. (kind: foundation · also known as: surfaces, backdrop-filter, frosted) - [Choosing a layer](https://opsinjs.pensievelabs.org/foundations/materials/choosing-a-layer): A decision table from surface kind to rung, five nesting rules, and the three questions that resolve almost every case. (kind: foundation · also known as: which material, surface decision, nesting surfaces, when to use blur, layer choice) - [Performance budget](https://opsinjs.pensievelabs.org/foundations/materials/performance-budget): At most three composited surfaces on screen at once, why a blurred backdrop costs what it costs, and how to measure it on the phone your readers actually own. (kind: foundation · also known as: compositing budget, backdrop-filter cost, jank, mid-range android, scroll performance, three surfaces) - [Reduced transparency](https://opsinjs.pensievelabs.org/foundations/materials/reduced-transparency): A stated operating-system preference, answered rung by rung with an opaque fallback that changes paint and never layout. (kind: foundation · also known as: prefers-reduced-transparency, opaque fallback, translucency preference, no blur, translucency off) - [The contrast floor](https://opsinjs.pensievelabs.org/foundations/materials/the-contrast-floor): Every translucent surface gets a minimum backing tint, so text contrast never depends on what is behind it, plus the worst-case composite and the scrim rule. (kind: foundation · also known as: minimum opacity, backing tint, scrim, worst case composite, text over image, glass legibility) - [The ladder](https://opsinjs.pensievelabs.org/foundations/materials/the-ladder): The six named rungs are canvas, card, raised, sheet, overlay and scrim, each with its job, its eight properties and its opaque fallback. (kind: foundation · also known as: material rungs, surface ladder, canvas card raised sheet overlay scrim, elevation levels) - [Material tokens](https://opsinjs.pensievelabs.org/foundations/materials/tokens): The generated reference for all six rungs covers eight properties each, both themes, and the preference overrides that replace them. (kind: foundation · also known as: material tokens, opsin-material, surface tokens, blur token, scrim token) - [Motion](https://opsinjs.pensievelabs.org/foundations/motion): Motion for a product somebody opens when worried. What it may do, the four health rules it must never break, and when the right amount of animation is none. (kind: foundation · also known as: motion principles, when not to animate) - [Choreography](https://opsinjs.pensievelabs.org/foundations/motion/choreography): What moves together and in what order. Continuity over replacement, morph rather than swap, depth rather than translation, and one thing moving at a time. (kind: foundation · also known as: stagger, sequencing, shared element, morph transition) - [Reduced motion](https://opsinjs.pensievelabs.org/foundations/motion/reduced-motion): What each motion token becomes when a reader asks for less movement. A stated reduced variant per token, not a kill switch that leaves things teleporting. (kind: foundation · also known as: prefers-reduced-motion, vestibular, motion sensitivity) - [Springs as tokens](https://opsinjs.pensievelabs.org/foundations/motion/springs-as-tokens): How a spring described by stiffness, damping and mass is sampled into a CSS linear() easing at build time, so a physical curve survives as a token. (kind: foundation · also known as: easing, linear(), spring, cubic-bezier) - [Motion tokens](https://opsinjs.pensievelabs.org/foundations/motion/tokens): The generated reference for every duration, easing and spring in the system, with each curve plotted from the parameters it was derived from. (kind: foundation · also known as: duration tokens, easing tokens) - [Using motion](https://opsinjs.pensievelabs.org/foundations/motion/using-motion): Motion chosen by the job it does, with duration derived from distance. The five jobs are enter, exit, feedback, navigation and loading, plus the count-up rule. (kind: foundation · also known as: transition, enter animation, exit animation, count-up) - [Principles](https://opsinjs.pensievelabs.org/foundations/principles): Five rules that decide every other argument in opsinjs, each stated as a prohibition you can check rather than a value you can agree with. (kind: foundation · also known as: design principles) - [Shape](https://opsinjs.pensievelabs.org/foundations/shape): Why the corners in a health product are superellipses rather than circular arcs, what shape is allowed to mean, and the one thing it must never carry. (kind: foundation · also known as: corners, corner rounding, corner geometry) - [Radius scale](https://opsinjs.pensievelabs.org/foundations/shape/radius-scale): A ladder of rungs derived from a single root radius, named for the objects they belong to, plus the nesting rule that keeps concentric corners parallel. (kind: foundation · also known as: border radius, radius ladder, corner radius, concentric corners) - [Squircle](https://opsinjs.pensievelabs.org/foundations/shape/squircle): The corner-shape property, the superellipse parameter opsinjs ships, and why this is the safest progressive enhancement in the whole system. (kind: foundation · also known as: squircle, corner-shape, superellipse, continuous corners) - [Shape tokens](https://opsinjs.pensievelabs.org/foundations/shape/tokens): The generated reference for the root radius, the six rungs derived from it, and the corner shape they are drawn with. (kind: foundation · also known as: radius tokens, shape token reference) - [Sound and haptics](https://opsinjs.pensievelabs.org/foundations/sound-and-haptics): Whether urgency may be carried by a buzz or a chime, the three-pattern haptic vocabulary, and why opsinjs specifies both channels but ships neither. (kind: foundation · also known as: haptics, vibration, taptic, audio alert, chime) - [Space and density](https://opsinjs.pensievelabs.org/foundations/space): The case for a deliberately generous scale in a product people use one-handed while worried, what it costs, and the four responsive modes that decide what fits. (kind: foundation · also known as: spacing, whitespace, generous density) - [Density and touch](https://opsinjs.pensievelabs.org/foundations/space/density-and-touch): A 44pt floor measured on the interactive area rather than the visual box, the separation rule that stops adjacent mis-taps, and where a primary action belongs. (kind: foundation · also known as: touch target, hit area, thumb reach, target separation) - [Responsive modes](https://opsinjs.pensievelabs.org/foundations/space/responsive-modes): Four named modes, the rule that a wider screen shows more of the story rather than a bigger version of it, and why a component queries its container. (kind: foundation · also known as: breakpoints, mobile, tablet, wide, density) - [Spacing scale](https://opsinjs.pensievelabs.org/foundations/space/spacing-scale): A 4pt-derived scale with a named role for each step, so a gap is chosen by what it separates rather than by how it looks. (kind: foundation · also known as: 4pt grid, spacing steps, gutter, layout rhythm) - [Space tokens](https://opsinjs.pensievelabs.org/foundations/space/tokens): The generated reference for the root spacing value, the numeric steps derived from it, the named roles, the target floor and the four mode thresholds. (kind: foundation · also known as: spacing tokens, space token reference) - [Token architecture](https://opsinjs.pensievelabs.org/foundations/token-architecture): The three tiers a token can live in, the one direction references are allowed to point, and why a component may never reach past the semantic layer. (kind: foundation · also known as: three tiers, primitive tokens, semantic tokens, component tokens) - [Typography](https://opsinjs.pensievelabs.org/foundations/typography): Why opsinjs ships no webfont, what the platform UI font buys a health product, and the four rules every piece of type in the system obeys. (kind: foundation · also known as: font, system-ui, typeface, platform font) - [Dynamic Type](https://opsinjs.pensievelabs.org/foundations/typography/dynamic-type): The reader's own text-size multiplier, the 1.3× bar every component must clear without breaking, and the layout habits that decide whether it does. (kind: foundation · also known as: dynamic type, text size multiplier, font scaling, larger text) - [Typography tokens](https://opsinjs.pensievelabs.org/foundations/typography/tokens): The generated reference for every type role, with a rendered specimen for each. Each entry lists the role's size, line height, tracking and weight. (kind: foundation · also known as: font tokens, text tokens, type token reference) - [Type scale](https://opsinjs.pensievelabs.org/foundations/typography/type-scale): A scale named for jobs rather than sizes, one family of reading roles, and why a measurement gets tabular figures from an attribute, not a separate family. (kind: foundation · also known as: text styles, type ramp, semantic type scale, tabular numerals) ## Accessibility Split by role, with a curated path for compliance reviewers and generated, dated contrast measurements. - [Accessibility](https://opsinjs.pensievelabs.org/accessibility): What opsinjs guarantees, what your product still owns, and how to check either one without taking our word for it. (kind: accessibility · also known as: a11y, wcag 2.2, accessibility overview) - [Accessibility statement](https://opsinjs.pensievelabs.org/accessibility/accessibility-statement): A dated, honest statement of what has and has not been assessed, written so that a reviewer can tell the difference. (kind: accessibility · also known as: conformance claim, known issues, statement of accessibility) - [Cognitive accessibility](https://opsinjs.pensievelabs.org/accessibility/cognitive-accessibility): Reducing load, removing time limits and making every error recoverable is the accessibility work that matters most in health and is measured least. (kind: accessibility · also known as: 3.2.4, time limits, memory load, easy read) - [Colour independence](https://opsinjs.pensievelabs.org/accessibility/colour-independence): Clinical status must survive greyscale, colour vision deficiency and a photocopier. The word is what makes that true. (kind: accessibility · also known as: 1.4.1, greyscale test, use of colour) - [Conformance report (VPAT/ACR)](https://opsinjs.pensievelabs.org/accessibility/conformance-report): A complete WCAG 2.2 Level A and AA accessibility conformance report in which every criterion is honestly marked Not Evaluated. (kind: accessibility · also known as: vpat, acr, section 508, en 301 549) - [Contrast conformance](https://opsinjs.pensievelabs.org/accessibility/contrast-conformance): The measured contrast of every published token pair, in both themes, generated and dated rather than asserted. (kind: accessibility · also known as: measured contrast, contrast results, 1.4.3, 1.4.11) - [For compliance reviewers](https://opsinjs.pensievelabs.org/accessibility/for-compliance-reviewers): A curated twenty-minute path through the evidence, written to be printed and to be honest about what has not been evaluated. (kind: accessibility · also known as: auditor, procurement, review path) - [For content](https://opsinjs.pensievelabs.org/accessibility/for-content): Headings, link text, alternative text and plain language, checked while you write rather than at audit. (kind: accessibility · also known as: accessible writing, heading order, link text) - [For designers](https://opsinjs.pensievelabs.org/accessibility/for-designers): The five checks to run on a health screen before it leaves your hands, and the three decisions only a designer can get wrong. (kind: accessibility · also known as: design review, before handoff, design checks) - [For developers](https://opsinjs.pensievelabs.org/accessibility/for-developers): Semantics, names, roles, state and focus order are split between what the components will do for you and what your JSX still has to get right. (kind: accessibility · also known as: aria, accessible name, focus order, semantics) - [For testing](https://opsinjs.pensievelabs.org/accessibility/for-testing): The manual and automated passes that make up an accessibility test plan for a health screen, and how to reproduce each one. (kind: accessibility · also known as: qa, test plan, accessibility testing, axe) - [Increased contrast](https://opsinjs.pensievelabs.org/accessibility/increased-contrast): What prefers-contrast changes, what forced-colours mode does instead, and an honest account of the per-component answers that exist while no global one does. (kind: accessibility · also known as: high contrast mode, forced-colors, windows contrast themes) - [Keyboard and focus](https://opsinjs.pensievelabs.org/accessibility/keyboard-and-focus): The global keyboard contract every opsinjs component inherits, and the focus rules that a health screen breaks most often. (kind: accessibility · also known as: tab order, focus visible, 2.1.1, 2.4.11) - [Print and export](https://opsinjs.pensievelabs.org/accessibility/print-and-export): Compliance reviewers read on paper and patients print results for appointments. What the print stylesheet does, and what a printed health value must carry. (kind: accessibility · also known as: print stylesheet, pdf, paper, photocopy) - [Reduced motion](https://opsinjs.pensievelabs.org/accessibility/reduced-motion): Reduced motion is a per-token degradation, not a kill switch. This page says what every animated token collapses to, and why the state change survives. (kind: accessibility · also known as: 2.3.3, 2.2.2, reduce motion setting) - [Reduced transparency](https://opsinjs.pensievelabs.org/accessibility/reduced-transparency): What each rung of the material ladder becomes when the reader has asked for less translucency. The layout must not move, and this page says why. (kind: accessibility · also known as: reduce transparency setting, backdrop blur off, frosted glass) - [Screen readers](https://opsinjs.pensievelabs.org/accessibility/screen-readers): The combinations we intend to test, the announcement contract every status change must satisfy, and an honest table of untested cells. (kind: accessibility · also known as: voiceover, nvda, jaws, talkback, live region) - [Target size and motor accessibility](https://opsinjs.pensievelabs.org/accessibility/target-size-and-motor): Why the floor here is 44 CSS pixels rather than the WCAG 2.2 minimum of 24, and what else a shaking hand needs. (kind: accessibility · also known as: 44pt, 2.5.8, 2.5.5, tremor, mis-tap) - [Text resizing and zoom](https://opsinjs.pensievelabs.org/accessibility/text-resizing-and-zoom): The 200% text check and the 400% reflow check are different tests that fail in different ways. It also says why a truncated number is a safety defect. (kind: accessibility · also known as: 200 percent, 400 percent reflow, 1.4.4, 1.4.10) - [This site's accessibility](https://opsinjs.pensievelabs.org/accessibility/this-site): The documentation site held to the standard it publishes. It records the places where it currently fails. (kind: accessibility · also known as: docs site accessibility, dogfooding) ## Content & language Writing for a patient reader: voice and tone across the four status levels, health literacy, and the plain-English A to Z. - [Content & language](https://opsinjs.pensievelabs.org/content): Why the words are part of the design system when the reader is a patient, and the five rules that apply to every string in the product. (kind: content · also known as: content design, ux writing, microcopy) - [Alt text and descriptions](https://opsinjs.pensievelabs.org/content/alt-text-and-descriptions): How to describe a dial, a range, a trend and a body map so that the non-visual version answers the same question as the picture. (kind: content · also known as: alt text, image description, long description, chart description) - [Asking sensitive questions](https://opsinjs.pensievelabs.org/content/asking-sensitive-questions): How to ask something personal in a health form. Say why you are asking, make optional genuinely optional, and never make the answer feel like a confession. (kind: content · also known as: sensitive questions, why we ask, optional questions, form copy) - [Error and empty messages](https://opsinjs.pensievelabs.org/content/error-and-empty-messages): What to say when there is nothing to show, when the data is stale, and when it broke. It also covers the one failure that must never be silent. (kind: content · also known as: error copy, empty state copy, failure wording, stale data copy) - [Glossary](https://opsinjs.pensievelabs.org/content/glossary): The A to Z as data. The record shape, how Term resolves an entry, how to propose one, and where the machine-readable copy lives. (kind: content · also known as: term definitions, word list, glossary data) - [Grammar and mechanics](https://opsinjs.pensievelabs.org/content/grammar-and-mechanics): Capitalisation, punctuation, lists, abbreviations and the typography of a number and its unit are the mechanical rules that Value and RelativeTime are built on. (kind: content · also known as: capitalisation, sentence case, punctuation, abbreviations, unit formatting) - [Health literacy](https://opsinjs.pensievelabs.org/content/health-literacy): Writing for the reader who can read the words but cannot use the numbers. For most health content, that is most readers. (kind: content · also known as: health numeracy, low literacy, comprehension, writing for patients) - [Inclusive content](https://opsinjs.pensievelabs.org/content/inclusive-content): The language choices about age, disability, gender, ethnicity, body and skin decide whether a health app is written for everybody or for a default reader. (kind: content · also known as: inclusive language, person first, identity first, respectful language) - [Numbers, dates and time](https://opsinjs.pensievelabs.org/content/numbers-dates-and-time): The prose style guide for dates, times, durations and ranges. It also covers the moment when "2 hours ago" becomes dangerous. (kind: content · also known as: date format, time format, relative time, ordinals) - [Plain-English A to Z](https://opsinjs.pensievelabs.org/content/plain-english-a-z): The canonical clinical-to-plain vocabulary, the rule for choosing a replacement word, and the machine-readable list every product and Term instance shares. (kind: content · also known as: clinical vocabulary, plain words, clinical terms, a to z) - [Reading level](https://opsinjs.pensievelabs.org/content/reading-level): The target we write to, how a readability score is calculated, and why the score is a diagnostic rather than the goal. (kind: content · also known as: readability score, grade level, plain language score) - [Voice and tone](https://opsinjs.pensievelabs.org/content/voice-and-tone): One voice, four tones. The voice is calm, plain and in the second person, and the register is set by the seriousness of the news rather than by the brand. (kind: content · also known as: tone of voice, second person, register) - [Writing status and alerts](https://opsinjs.pensievelabs.org/content/writing-status-and-alerts): One sentence pattern per clinical status level, the words banned at each, and how to write when the news is bad. (kind: content · also known as: alert copy, warning wording, escalation copy, breaking bad results) ## Patterns Components, tokens and guidance assembled for exactly one user task such as disclosing a result, logging daily or escalating an alert. - [Patterns](https://opsinjs.pensievelabs.org/patterns): A pattern is one user task spelled out across the screens it takes. It names the components, the copy and the failure cases, in the order the reader meets them. (kind: pattern · also known as: pattern library, user flows, multi-screen sequences) - [Alert escalation](https://opsinjs.pensievelabs.org/patterns/alert-escalation): Moving from ambient to interruptive without spending attention you will need later. The four rungs, the per-session budget, and visible de-escalation. (kind: pattern · also known as: escalation ladder, interruptive alerts, alert budget, when to interrupt) - [Ask users for…](https://opsinjs.pensievelabs.org/patterns/ask-users-for): Patterns keyed by the data being requested rather than the screen. Every health product asks for the same fifteen things and gets the same eight of them wrong. (kind: pattern · also known as: asking for personal data, what to collect, data collection patterns, field-level guidance) - [Ask users for contact details](https://opsinjs.pensievelabs.org/patterns/ask-users-for/contact-details): Ask for the channel you will actually use, verify it before you rely on it, and remember that a health message arriving on the wrong device is a disclosure. (kind: pattern · also known as: email field, phone number field, address field, contact preferences, verification) - [Ask users for a date of birth](https://opsinjs.pensievelabs.org/patterns/ask-users-for/date-of-birth): Three text fields, not a calendar. First, the question of whether an age band would have done instead. (kind: pattern · also known as: date of birth field, DOB input, birthday field, age band, date picker for birth date) - [Ask users for ethnicity](https://opsinjs.pensievelabs.org/patterns/ask-users-for/ethnicity): Optional, explained, self-identified, and never used to adjust a clinical threshold without a named clinical owner. (kind: pattern · also known as: ethnicity field, ethnic group question, race field, health equity data) - [Ask users for height and weight](https://opsinjs.pensievelabs.org/patterns/ask-users-for/height-and-weight): Compound units, a reader who may find the question difficult, and a derived number a design system should be very careful about showing. That number is BMI. (kind: pattern · also known as: height field, weight field, stones and pounds, feet and inches, BMI input) - [Ask users for medications](https://opsinjs.pensievelabs.org/patterns/ask-users-for/medications): A medication is not a string. It is a name, a strength, a form and a schedule, entered by somebody reading a box in poor light. (kind: pattern · also known as: medication list, drug name entry, dose entry, prescription input, what medicines do you take) - [Ask users for a name](https://opsinjs.pensievelabs.org/patterns/ask-users-for/name): One field wherever possible, no assumptions about structure, and the difference between the name on a record and the name someone wants to be called. (kind: pattern · also known as: name field, full name input, first and last name, preferred name, legal name) - [Ask users for sex and gender](https://opsinjs.pensievelabs.org/patterns/ask-users-for/sex-and-gender): Two different questions with two different purposes. Ask the one your product actually needs, and never let one field answer both. (kind: pattern · also known as: sex or gender field, gender field, sex assigned at birth, trans inclusive form, gender identity) - [Ask users for symptoms](https://opsinjs.pensievelabs.org/patterns/ask-users-for/symptoms): Free text with a structured assist, never a closed list. The hard rule is that collecting a symptom is not the same as assessing it. (kind: pattern · also known as: symptom entry, describe your symptoms, symptom checker input) - [Consent and permissions](https://opsinjs.pensievelabs.org/patterns/consent-and-permissions): Asking for access at the moment it is needed, explaining what it buys, recording what was agreed, and making withdrawal as easy as agreement. (kind: pattern · also known as: permission priming, asking for consent, permission prompt sequence, revoking access, data sharing prompt) - [Daily logging](https://opsinjs.pensievelabs.org/patterns/daily-logging): The repeated-entry flow is designed for the ninetieth entry rather than the first, where every saved second compounds and every extra field costs adherence. (kind: pattern · also known as: logging a reading, repeated entry, diary entry, tracking flow, quick add) - [Empty and first use](https://opsinjs.pensievelabs.org/patterns/empty-and-first-use): The surface before there is anything to show. There are six kinds of nothing, and rendering the wrong one is a safety problem rather than a polish problem. (kind: pattern · also known as: empty state, zero data, nothing to show, first use screen, no readings yet) - [Form design](https://opsinjs.pensievelabs.org/patterns/forms): How many questions per page, when validation fires, and how errors are surfaced. The behaviour of a question, as distinct from the code that wires a form up. (kind: pattern · also known as: form design, question design, form UX, how forms should behave) - [Autocomplete and input types](https://opsinjs.pensievelabs.org/patterns/forms/autocomplete-and-input-types): The attributes that decide which keyboard appears and whether the browser can fill a field, including the health fields for which no autofill token exists. (kind: pattern · also known as: autocomplete attribute, inputmode, input type number, keyboard type, autofill) - [Error summaries](https://opsinjs.pensievelabs.org/patterns/forms/error-summaries): Where the summary goes on a failed submit, what it contains, where focus lands, and why the summary is not a substitute for the inline message. (kind: pattern · also known as: error summary, form errors on submit, error list, focus on error) - [Question pages](https://opsinjs.pensievelabs.org/patterns/forms/question-pages): One question per page or several grouped. How to decide, what one-per-page costs, and the cases in health where grouping is the safer answer. (kind: pattern · also known as: one question per page, one thing per page, grouped questions, form layout decision) - [Required and optional](https://opsinjs.pensievelabs.org/patterns/forms/required-and-optional): Mark one or the other but never both. In a health product, prefer marking optional, because it makes the cost of every required field visible. (kind: pattern · also known as: required fields, optional fields, asterisk convention, marking required) - [Units and numeric entry](https://opsinjs.pensievelabs.org/patterns/forms/units-and-numeric-entry): Accepting a number that has a unit attached. The unit never sits inside the field, the value is never ambiguous, and a surprising reading is never rejected. (kind: pattern · also known as: entering a unit, numeric input health, mmol or mg, unit picker, compound units) - [Validation timing](https://opsinjs.pensievelabs.org/patterns/forms/validation-timing): When a check should run. Why validating on every keystroke is both the most common choice and the worst one for the readers who most need help. (kind: pattern · also known as: when to validate, live validation, on blur validation, inline errors timing) - [Offline and stale data](https://opsinjs.pensievelabs.org/patterns/offline-and-stale-data): What a health screen shows when it cannot vouch for its numbers. It degrades assertions rather than hiding them, and never lets a cached value pass as current. (kind: pattern · also known as: offline mode, stale readings screen, last synced, cached readings, no connection) - [Onboarding and first run](https://opsinjs.pensievelabs.org/patterns/onboarding-and-first-run): The minimum you may collect before the reader has seen anything of value, and how to defer everything else to the moment it earns its keep. (kind: pattern · also known as: first run, signup flow, setup wizard, minimum collection, time to first value) - [Result disclosure](https://opsinjs.pensievelabs.org/patterns/result-disclosure): Showing someone a result they may not want to see, without ambush. The sequence from notification to number to next step. (kind: pattern · also known as: showing a result, lab result flow, disclosing a test result, result ambush) - [Sharing with a clinician](https://opsinjs.pensievelabs.org/patterns/sharing-with-a-clinician): Export, summary and hand-off surfaces produce something a clinician can read in ninety seconds without the product implying it has done any interpreting. (kind: pattern · also known as: export my data, share with doctor, appointment summary, printable report, hand-off) - [Trend review](https://opsinjs.pensievelabs.org/patterns/trend-review): Reading change over time without over-interpreting noise. Minimum windows, honest axes, and separating direction from valence. (kind: pattern · also known as: trends over time, change over time, chart review, is it going up, noise vs signal) ## Handbook Mechanics: styling hooks, data attributes, composition, forms, dark mode, error codes, and how to contribute a component. - [Handbook](https://opsinjs.pensievelabs.org/handbook): The mechanics layer is how you change things. It is kept deliberately separate from what a token means and from the generated list of every one. (kind: handbook · also known as: handbook, mechanics, how do I change this, developer guide) - [Composition and render](https://opsinjs.pensievelabs.org/handbook/composition-and-render): Merging an opsinjs part into your own element with the render prop. How props and refs are combined, and the three ways it goes wrong. (kind: handbook · also known as: render prop, asChild, polymorphic component, ref forwarding, wrapping a component) - [Contributing](https://opsinjs.pensievelabs.org/handbook/contributing): How a change gets into opsinjs. The four routes in, what each one has to clear, and the one thing that will get a component proposal rejected fastest. (kind: handbook · also known as: how to contribute, contribution guide, submitting a change, proposing something) - [Code style](https://opsinjs.pensievelabs.org/handbook/contributing/code-style): The conventions a reviewer will hold you to. The named-props-interface rule, what the formatter owns, and the handful of choices that are not negotiable. (kind: handbook · also known as: code conventions, style guide, prettier config, lint config, house style) - [Component checklist](https://opsinjs.pensievelabs.org/handbook/contributing/component-checklist): The definition of done across design, code, tokens, tests, accessibility, documentation and safety. The items that are actually enforced are marked as such. (kind: handbook · also known as: definition of done, component checklist, ship criteria, release checklist) - [Contributing tokens](https://opsinjs.pensievelabs.org/handbook/contributing/contributing-tokens): Adding or changing a token, and the migration obligation it creates. That obligation exists because a CSS custom property is a public API covered by semver. (kind: handbook · also known as: adding a token, changing a token, token migration, deprecating a token) - [Documentation templates](https://opsinjs.pensievelabs.org/handbook/contributing/documentation-templates): Twelve page kinds, each with a fixed set of headings the build enforces. The outlines are published verbatim, so a contributor fills in a template. (kind: handbook · also known as: page templates, section outlines, page kinds, what headings does this page need) - [Proposing a component](https://opsinjs.pensievelabs.org/handbook/contributing/proposing-a-component): The intake questions a proposal must answer before an API is worth discussing. The four reasons a proposal is normally rejected. (kind: handbook · also known as: component proposal, intake criteria, new component request, propose a new component, propose a component, request a component) - [Dark mode](https://opsinjs.pensievelabs.org/handbook/dark-mode): One class on the root element, one provider, and the two-line inline script that prevents the flash. Dark mode is a contrast problem before a colour problem. (kind: handbook · also known as: dark theme, next-themes, ssr flash, theme class strategy, theme toggle) - [Data attributes](https://opsinjs.pensievelabs.org/handbook/data-attributes): The shared state-attribute vocabulary. Where it comes from, which attributes are Base UI's and which are opsinjs's, and why it is a versioned contract. (kind: handbook · also known as: data-open, data-status, data-starting-style, state attributes, styling state) - [Error codes](https://opsinjs.pensievelabs.org/handbook/error-codes): Every development-mode warning opsinjs will emit, its stable code, what causes it, and the page that prevents it happening again. (kind: handbook · also known as: warning codes, dev warnings, OPSIN error, console warning, what does this warning mean) - [Forms](https://opsinjs.pensievelabs.org/handbook/forms): Wiring a Field to React Hook Form, TanStack Form or a native form. The validation boundary, server errors, and the accessibility the wiring must not lose. (kind: handbook · also known as: react hook form, tanstack form, form wiring, form validation setup, controlled input) - [Icons](https://opsinjs.pensievelabs.org/handbook/icons): Bring your own icon set. This page covers the slot contract, the sizing rule, and the hard prohibition on an icon carrying clinical status by itself. (kind: handbook · also known as: icon slot contract, bring your own icons, passing an icon prop, which icon set) - [Internationalisation](https://opsinjs.pensievelabs.org/handbook/internationalisation): RTL, locale formatting, and the hard part. That part is translating a status vocabulary without changing what it means clinically. (kind: handbook · also known as: internationalisation mechanics, rtl, right to left, locale formatting, translating status) - [Migrating from shadcn/ui](https://opsinjs.pensievelabs.org/handbook/migrating-from-shadcn): The token map, the component equivalences and the API translations. It ends with an honest list of what opsinjs has no equivalent for. (kind: handbook · also known as: shadcn migration, radix to base ui, asChild to render, moving from shadcn, token mapping) - [Motion in practice](https://opsinjs.pensievelabs.org/handbook/motion-in-practice): Writing enter and exit transitions against data-starting-style and data-ending-style, with a reduced-motion fallback that is per token, not a kill switch. (kind: handbook · also known as: enter transition, exit transition css, prefers-reduced-motion css, animating a popup, writing a css transition) - [Naming conventions](https://opsinjs.pensievelabs.org/handbook/naming-conventions): The published naming contract for component ids, prop names, token names, data attributes, files and CSS custom properties, and where the two spellings diverge. (kind: handbook · also known as: naming rules, kebab case or pascal case, what to call a token, prop naming, file naming) - [Performance and bundle size](https://opsinjs.pensievelabs.org/handbook/performance-and-bundle-size): What each component will cost, the composited-surface budget that matters more than kilobytes, and how to measure both rather than argue about them. (kind: handbook · also known as: bundle size, performance budget, tree shaking, composited surfaces, measuring cost) - [Server and client components](https://opsinjs.pensievelabs.org/handbook/server-and-client-components): Where the client boundary falls, what is safe to render on the server, and why importing one interactive component can turn a whole page into client code. (kind: handbook · also known as: rsc boundary, use client, client boundary, provider placement, where does use client go) - [Styling](https://opsinjs.pensievelabs.org/handbook/styling): className, data attributes, CSS variables and the style prop are the four override hooks, listed in their fixed order of preference, with the rule for choosing. (kind: handbook · also known as: className override, how to style a component, cn function, css variable override) - [Testing your integration](https://opsinjs.pensievelabs.org/handbook/testing): What to assert about a component you did not write. The stable contracts, the accessibility assertions worth copying, and the tests that break on any refactor. (kind: handbook · also known as: testing components, what to assert, integration tests, asserting accessibility, testing library) - [Tooling](https://opsinjs.pensievelabs.org/handbook/tooling): Two lint plugins that turn the system's most important rules from advice into build failures. A rule enforced only by review is a rule enforced only sometimes. (kind: handbook · also known as: lint rules, eslint plugin, stylelint plugin, enforcing the rules) - [ESLint plugin](https://opsinjs.pensievelabs.org/handbook/tooling/eslint-plugin): The proposed rule set for JSX and TypeScript covers raw colours, mixed axes, banned words, and the component contracts a reviewer should not have to remember. (kind: handbook · also known as: eslint-plugin-opsinjs, lint rules jsx, no-raw-color, no-mixed-axes) - [Stylelint plugin](https://opsinjs.pensievelabs.org/handbook/tooling/stylelint-plugin): The proposed CSS rule set catches hardcoded colours, tier violations, and a status token applied to a category surface. (kind: handbook · also known as: stylelint-plugin-opsinjs, css lint rules, token tier enforcement, no hardcoded colour css) - [TypeScript](https://opsinjs.pensievelabs.org/handbook/typescript): The exported surface comprises named prop interfaces, the ClinicalStatus and HealthCategory unions, and the rule that makes generated API tables possible. (kind: handbook · also known as: types, ClinicalStatus type, HealthCategory type, props interface, generated props table) ## Theming & tokens How to change what a token means. This section covers the theme generator, preset codes, category and status palettes, and Tailwind v4 ordering traps. - [Theming & tokens](https://opsinjs.pensievelabs.org/theming): The three tiers of the opsinjs token system, which tier you are allowed to change, and what the system refuses to let you change at all. (kind: guide · also known as: theme, retheme, token tiers, design tokens) - [Adding your own tokens](https://opsinjs.pensievelabs.org/theming/adding-your-own-tokens): How to add a token the system does not have, in a way that survives an opsinjs upgrade instead of being overwritten by one. (kind: guide · also known as: custom token, extend tokens, new token, my own variables) - [Category palettes](https://opsinjs.pensievelabs.org/theming/category-palettes): How to add or retune a health category ramp without letting it leak into the axis that carries clinical urgency. (kind: guide · also known as: add a category, seventh category, category ramp) - [CSS variables](https://opsinjs.pensievelabs.org/theming/css-variables): Consuming opsinjs tokens as raw custom properties, with no Tailwind, no build step and no React. (kind: guide · also known as: custom properties, vanilla css, without tailwind, css-in-js tokens) - [Design handoff](https://opsinjs.pensievelabs.org/theming/design-handoff): Getting the opsinjs token system into a design tool without retyping it, and keeping the two in step once you have. (kind: guide · also known as: figma, DTCG, design tokens export, figma variables, handoff) - [Lyra and the docs chrome](https://opsinjs.pensievelabs.org/theming/lyra-and-the-docs-chrome): This documentation site is dense, square and neutral. The design system it documents is none of those things, and the difference is deliberate. (kind: project · also known as: docs chrome, why does this site look like this, lyra, product theme) - [Presets](https://opsinjs.pensievelabs.org/theming/presets): How a whole opsinjs theme is packaged as one installable artifact, why opsinjs preset names are namespaced, and which presets exist today. (kind: guide · also known as: preset, theme preset, opsinjs-calm, shareable theme) - [Status palettes](https://opsinjs.pensievelabs.org/theming/status-palettes): Why the four clinical status ramps are the one part of the token system opsinjs asks you not to redefine, and what to do when you have to anyway. (kind: guide · also known as: status colour, redefine status, four levels, urgent colour) - [Tailwind v4](https://opsinjs.pensievelabs.org/theming/tailwind-v4): How opsinjs uses @theme, @theme inline and @source, and the three CSS ordering mistakes that break a theme without producing an error. (kind: guide · also known as: @theme inline, @source, tailwind 4, css import order) - [Theme generator](https://opsinjs.pensievelabs.org/theming/theme-generator): Turn one brand colour into a complete, gamut-aware, contrast-validated opsinjs theme, and understand every step it took to get there. (kind: guide · also known as: generate a theme, brand colour to theme, colour ramp generator) - [Token reference](https://opsinjs.pensievelabs.org/theming/token-reference): Every opsinjs token you are allowed to set, grouped by tier, with what it controls and which parts of the system read it. (kind: reference · also known as: token list, settable tokens, what tokens exist) - [Validating your theme](https://opsinjs.pensievelabs.org/theming/validating-your-theme): How to prove your own theme is legible, and why every contrast number published on this site describes the shipped presets and not your colours. (kind: guide · also known as: check-theme, contrast CI, validate colours, theme lint) ## Agents & automation The surfaces that are contractually stable for machines, and the rules an assistant must follow to generate safe health UI. - [Agents & automation](https://opsinjs.pensievelabs.org/agents): Which surfaces of this site are a contract a machine can rely on, which are not, and what an agent is expected to do when the answer is "that does not exist". (kind: guide · also known as: llm, ai agent, machine readable, copilot, code generation) - [Agent skill](https://opsinjs.pensievelabs.org/agents/agent-skill): Install the opsinjs skill so that the clinical and token rules apply to every generation, without pasting them into a prompt each time. (kind: guide · also known as: skill, skills.sh, claude skill, install rules) - [Evals](https://opsinjs.pensievelabs.org/agents/evals): The task suite that checks whether these docs answer the questions an agent asks, at the address it would guess. What each task asserts, and how it is scored. (kind: reference · also known as: eval suite, agent scores, benchmark, model evaluation) - [llms.txt and the shards](https://opsinjs.pensievelabs.org/agents/llms-txt): The curated index a model should read first, the four topic shards that exist because context windows are finite, and the size budget that governs them. (kind: guide · also known as: llms.txt, llms-full.txt, shards, context budget) - [Machine-readable schemas](https://opsinjs.pensievelabs.org/agents/machine-readable-schemas): The catalogue, the token set, the status vocabulary and the glossary as JSON at stable paths, so a tool can resolve a fact instead of parsing prose. (kind: guide · also known as: json api, catalogue json, schemas, structured data) - [MCP server](https://opsinjs.pensievelabs.org/agents/mcp-server): Point the shadcn MCP server at the opsinjs registry so an assistant can browse and install real items instead of guessing at them. (kind: guide · also known as: mcp, model context protocol, claude code setup, cursor setup) - [Offline docs bundle](https://opsinjs.pensievelabs.org/agents/offline-docs-bundle): The whole documentation corpus as one versioned JSON file, for agents and tools that run without network access. (kind: guide · also known as: /r/docs.json, offline, air-gapped, bundle) - [Prompt recipes](https://opsinjs.pensievelabs.org/agents/prompt-recipes): Prompts that reliably produce correct, safe health UI, with the reasoning for every constraint so you can adapt them rather than copy them. (kind: guide · also known as: prompts, prompt engineering, how to ask, generation recipes) - [Raw markdown API](https://opsinjs.pensievelabs.org/agents/raw-markdown-api): Every documentation page is available as markdown at the same URL with .md appended. You get processed markdown, not MDX source, with components left as tags. (kind: guide · also known as: .md, markdown twin, copy page, page as markdown) - [Rules for agents](https://opsinjs.pensievelabs.org/agents/rules-for-agents): The hard rules a model must follow when generating opsinjs UI, written as prohibitions you can test rather than principles you can nod at. (kind: handbook · also known as: agent rules, system prompt, do not invent, generation rules) - [Writing docs for agents](https://opsinjs.pensievelabs.org/agents/writing-docs-for-agents): The authoring rules that keep a page legible to a machine, without making it worse for the person who has to read it. (kind: handbook · also known as: machine-legible, authoring for llms, docs style for agents) ## Registry & distribution Shipping as a shadcn-spec registry: namespaces, registry.json, preset codes and upgrade diffs. - [Registry & distribution](https://opsinjs.pensievelabs.org/registry): opsinjs is distributed as a shadcn-spec registry rather than as an npm package, and this is what that decision buys and what it costs. (kind: guide · also known as: distribution, install, copy not dependency, shadcn registry) - [CLI reference](https://opsinjs.pensievelabs.org/registry/cli-reference): The commands you actually need, which of them are shadcn's, and why opsinjs deliberately ships almost no CLI of its own. (kind: guide · also known as: cli, commands, shadcn add, terminal) - [Namespaces](https://opsinjs.pensievelabs.org/registry/namespaces): Register @opsinjs in your project, compose it with other registries, and understand what a namespace does and does not guarantee. (kind: guide · also known as: @opsinjs, registries config, compose registries, private registry) - [Preset codes](https://opsinjs.pensievelabs.org/registry/preset-codes): The short code that carries a whole theme, how opsinjs namespaces its own, and how to encode, decode and apply one. (kind: guide · also known as: preset code, decode, apply theme, share a theme) - [registry-item.json](https://opsinjs.pensievelabs.org/registry/registry-item-json): One distributed item annotated field by field, covering files, targets, dependencies and CSS variables, and the fields opsinjs deliberately leaves empty. (kind: guide · also known as: registry item, item schema, item json, cssVars) - [registry.json](https://opsinjs.pensievelabs.org/registry/registry-json): The catalog file annotated field by field, with the opsinjs conventions layered on top of the shadcn specification. (kind: guide · also known as: catalog, registry schema, registry root) - [Self-hosting a fork](https://opsinjs.pensievelabs.org/registry/self-hosting-a-fork): Running your own registry from a fork of opsinjs. What to change, what to keep, and how to stay able to take updates. (kind: guide · also known as: fork, internal design system, self host, run your own registry) - [Upgrades and diffs](https://opsinjs.pensievelabs.org/registry/upgrades-and-diffs): How to take an update to code you own and have already edited, without either losing your changes or silently keeping a bug. (kind: guide · also known as: upgrade, update components, three-way merge, --diff, fork problem, file provenance) ## Reference The generated list of every token, data attribute, CSS variable, key binding, type, contrast pair and glossary term. - [Reference](https://opsinjs.pensievelabs.org/reference): Written by a script from the same source the build uses, covering every token, data attribute, CSS variable, key, exported type and defined term. (kind: reference · also known as: generated reference, what is generated) - [API](https://opsinjs.pensievelabs.org/reference/api): One page per exported symbol, at a guessable URL, so every type name in the documentation is a link rather than a dead end. (kind: reference · also known as: api index, symbol pages, exported symbols) - [AliasProblem](https://opsinjs.pensievelabs.org/reference/api/AliasProblem): One search synonym that cannot be used, either because two components claim it or because it collides with a component id. (kind: reference) - [ApcaVerdict](https://opsinjs.pensievelabs.org/reference/api/ApcaVerdict): The result of one APCA measurement, with the signed Lc, its polarity, the floor for that use, and how far above or below the floor it landed. (kind: reference) - [AxisConflict](https://opsinjs.pensievelabs.org/reference/api/AxisConflict): A refusal. (kind: reference) - [CatalogueIndexRow](https://opsinjs.pensievelabs.org/reference/api/CatalogueIndexRow): One component as the light registry index publishes it, flattened to the fields a decision to install actually turns on. (kind: reference) - [ClinicalStatus](https://opsinjs.pensievelabs.org/reference/api/ClinicalStatus): What a reading means and what, if anything, to do about it. (kind: reference · also known as: status type, status union) - [ClinicalStatusMeta](https://opsinjs.pensievelabs.org/reference/api/ClinicalStatusMeta): Everything a clinical status carries besides its colour. (kind: reference) - [ClinicalStatusOrUnknown](https://opsinjs.pensievelabs.org/reference/api/ClinicalStatusOrUnknown): The four clinical statuses plus `unknown`. (kind: reference) - [ColorInput](https://opsinjs.pensievelabs.org/reference/api/ColorInput): Anything the contrast functions accept: an sRGB triple, an OKLCH object, or a CSS colour string (`#0b6bcb`, `oklch(0.62 0.17 15)`, `rgb(11 107 203)`). (kind: reference) - [ContrastCheck](https://opsinjs.pensievelabs.org/reference/api/ContrastCheck): One measured pair from a derived theme, carrying both the APCA Lc and the WCAG ratio, the use that fixes the floor, and whether it passed. (kind: reference) - [ContrastUse](https://opsinjs.pensievelabs.org/reference/api/ContrastUse): What a pair is being used for. (kind: reference) - [CvdCollision](https://opsinjs.pensievelabs.org/reference/api/CvdCollision): Two colours that stop being distinguishable under one kind of colour vision deficiency, and the Lc left between them once simulated. (kind: reference) - [CvdType](https://opsinjs.pensievelabs.org/reference/api/CvdType): The three dichromacies, plus the achromatic check every specimen must also survive. (kind: reference) - [DataState](https://opsinjs.pensievelabs.org/reference/api/DataState): The state a data surface is in, named once so the surfaces converge on one vocabulary, though no component accepts it yet. (kind: reference) - [DecodeError](https://opsinjs.pensievelabs.org/reference/api/DecodeError): Why a preset code could not be read. (kind: reference) - [DecodeResult](https://opsinjs.pensievelabs.org/reference/api/DecodeResult): The outcome of reading a preset code. (kind: reference) - [DerivedTheme](https://opsinjs.pensievelabs.org/reference/api/DerivedTheme): Everything derivation produces from one brand colour. (kind: reference) - [DeriveOptions](https://opsinjs.pensievelabs.org/reference/api/DeriveOptions): The knobs on theme derivation. (kind: reference) - [DeriveWarning](https://opsinjs.pensievelabs.org/reference/api/DeriveWarning): One thing the derivation has to say about a theme, as a level, a stable code and a message. (kind: reference) - [Detent](https://opsinjs.pensievelabs.org/reference/api/Detent): How far a sheet is open. (kind: reference) - [Gamut](https://opsinjs.pensievelabs.org/reference/api/Gamut): The colour spaces this module can express a colour in. (kind: reference) - [GeneratedBannedWord](https://opsinjs.pensievelabs.org/reference/api/GeneratedBannedWord): One banned word: the word a component's copy must not use, what to write in its place, and why the word is barred. (kind: reference) - [HealthCategory](https://opsinjs.pensievelabs.org/reference/api/HealthCategory): What a reading is ABOUT. (kind: reference · also known as: category type, category union) - [Kind](https://opsinjs.pensievelabs.org/reference/api/Kind): A page's kind. (kind: reference) - [MaterialRung](https://opsinjs.pensievelabs.org/reference/api/MaterialRung): A rung of the material ladder, meaning how a surface sits above what is behind it. (kind: reference) - [Oklab](https://opsinjs.pensievelabs.org/reference/api/Oklab): A colour in OKLab. (kind: reference) - [Oklch](https://opsinjs.pensievelabs.org/reference/api/Oklch): A colour in OKLCH. (kind: reference) - [OpsinError](https://opsinjs.pensievelabs.org/reference/api/OpsinError): One warning code: what it is called, how severe it is, and the page that prevents it. (kind: reference) - [OpsinErrorCode](https://opsinjs.pensievelabs.org/reference/api/OpsinErrorCode): Every warning code opsinjs can emit. (kind: reference) - [OpsinErrorParams](https://opsinjs.pensievelabs.org/reference/api/OpsinErrorParams): The values a message template asks for, keyed by placeholder name. (kind: reference) - [OpsinErrorSeverity](https://opsinjs.pensievelabs.org/reference/api/OpsinErrorSeverity): How severe a warning is. (kind: reference) - [Preset](https://opsinjs.pensievelabs.org/reference/api/Preset): A theme as a person describes it. (kind: reference) - [Ramp](https://opsinjs.pensievelabs.org/reference/api/Ramp): One complete lightness ramp, as a value per step. (kind: reference) - [RampStep](https://opsinjs.pensievelabs.org/reference/api/RampStep): One rung of the lightness ladder, from 50 at the lightest to 950 at the darkest. (kind: reference) - [RampStepValue](https://opsinjs.pensievelabs.org/reference/api/RampStepValue): One rung of a ramp, as the sRGB value that ships, the wide-gamut value where P3 has headroom, and whether sRGB had to clamp the chroma away. (kind: reference) - [ReferenceRange](https://opsinjs.pensievelabs.org/reference/api/ReferenceRange): The interval a reading is being compared against, and who says so. (kind: reference) - [RefusedConversion](https://opsinjs.pensievelabs.org/reference/api/RefusedConversion): A pair people expect to be arithmetic and is not, with the reason. (kind: reference) - [RegistryLookup](https://opsinjs.pensievelabs.org/reference/api/RegistryLookup): Both call shapes are supported on purpose. (kind: reference) - [RegistryQuery](https://opsinjs.pensievelabs.org/reference/api/RegistryQuery): A request for one registry item, by id and optionally by base, style and kind. (kind: reference) - [Rgb](https://opsinjs.pensievelabs.org/reference/api/Rgb): Red, green and blue, each 0 to 1, in whichever space the function says. (kind: reference) - [Rgb255](https://opsinjs.pensievelabs.org/reference/api/Rgb255): A colour as 0 to 255 sRGB integers, which is what APCA is defined over. (kind: reference) - [RoleName](https://opsinjs.pensievelabs.org/reference/api/RoleName): The roles a derived theme guarantees. (kind: reference) - [RolePair](https://opsinjs.pensievelabs.org/reference/api/RolePair): One semantic role in both colour modes. (kind: reference) - [RoleValue](https://opsinjs.pensievelabs.org/reference/api/RoleValue): What a semantic role resolves to in one colour mode. (kind: reference) - [Status](https://opsinjs.pensievelabs.org/reference/api/Status): The release phase of a component page or a catalogue entry. (kind: reference) - [StatusMeta](https://opsinjs.pensievelabs.org/reference/api/StatusMeta): What a release phase shows on a badge. (kind: reference) - [TokenFormat](https://opsinjs.pensievelabs.org/reference/api/TokenFormat): The formats the `/tokens` and `/colors` browsers can copy a value in. (kind: reference) - [TrendPoint](https://opsinjs.pensievelabs.org/reference/api/TrendPoint): One reading in a series, for the components that draw change over time. (kind: reference) - [Unit](https://opsinjs.pensievelabs.org/reference/api/Unit): One unit: what it is called, what a reader sees, and how it is SPOKEN. (kind: reference) - [UnitConversion](https://opsinjs.pensievelabs.org/reference/api/UnitConversion): An exact conversion between two units of the same kind. (kind: reference) - [UnknownStatus](https://opsinjs.pensievelabs.org/reference/api/UnknownStatus): The absence of an assertion, which covers a reading never taken, a stale reading, or a reading whose reference range the product does not own. (kind: reference) - [UnresolvedReason](https://opsinjs.pensievelabs.org/reference/api/UnresolvedReason): Why a lookup came back empty. (kind: reference) - [ViewKind](https://opsinjs.pensievelabs.org/reference/api/ViewKind): What a `/view` route can render. (kind: reference) - [ViewParams](https://opsinjs.pensievelabs.org/reference/api/ViewParams): Everything a chrome-less preview URL can carry. (kind: reference) - [WarningLevel](https://opsinjs.pensievelabs.org/reference/api/WarningLevel): How serious a derivation warning is. (kind: reference) - [WcagUse](https://opsinjs.pensievelabs.org/reference/api/WcagUse): Which WCAG 2.2 contrast threshold applies. (kind: reference) - [WcagVerdict](https://opsinjs.pensievelabs.org/reference/api/WcagVerdict): The result of one WCAG 2.2 contrast measurement, with the ratio, the floor for that use, and the success criterion it is measured against. (kind: reference) - [Catalogue](https://opsinjs.pensievelabs.org/reference/generated/catalogue): Every component id the system has declared, with its category, its release phase and the search synonyms that reach it. (kind: reference · also known as: component list, does opsinjs have) - [Contrast](https://opsinjs.pensievelabs.org/reference/generated/contrast): Measured APCA Lc and WCAG 2.2 ratios for every token pair the system defines, in both themes, dated. (kind: reference · also known as: contrast measurements, generated contrast, Lc table) - [CSS variables](https://opsinjs.pensievelabs.org/reference/generated/css-variables): Every --opsin-* custom property, its default in both themes, what it controls and which selectors read it. (kind: reference · also known as: css vars, opsin variables, generated css variables) - [Data attributes](https://opsinjs.pensievelabs.org/reference/generated/data-attributes): Every data-* attribute the system emits, the condition that produces it, and the values it can take. (kind: reference · also known as: data-attributes, styling hooks, every data attribute) - [Glossary data](https://opsinjs.pensievelabs.org/reference/generated/glossary): The clinical-to-plain-English term list as a flat, searchable table. It is the machine twin of the Plain-English A to Z. (kind: reference · also known as: term data, glossary table, plain english data) - [Keyboard](https://opsinjs.pensievelabs.org/reference/generated/keyboard): Every keyboard interaction in the system, aggregated from the keyboard table on each component page. (kind: reference · also known as: key bindings, keyboard table, shortcuts) - [Tokens](https://opsinjs.pensievelabs.org/reference/generated/tokens): Every design token opsinjs defines, what it controls, and which parts of the system consume it. (kind: reference · also known as: all tokens, token index, complete token table) - [Types](https://opsinjs.pensievelabs.org/reference/generated/types): Every TypeScript symbol this documentation site's own lib/ exports, with a page of its own for each type and interface. (kind: reference · also known as: exported types, TypeScript API, ClinicalStatus, HealthCategory) - [System glossary](https://opsinjs.pensievelabs.org/reference/system-glossary): The words opsinjs uses about itself are rung, axis, role, base, style and preset. Each has one definition and the page that owns it. (kind: reference · also known as: rung, base vs style, what is a ladder, system vocabulary) ## Project State of the system, roadmap, release phases, versioning policy, decision records, changelog and licensing. - [Project](https://opsinjs.pensievelabs.org/project): What opsinjs is as a project rather than as a library. Its scope, its promises, who maintains it, and where each of those is written down. (kind: project · also known as: about the project, governance, who maintains opsinjs) - [Changelog](https://opsinjs.pensievelabs.org/project/changelog): What actually shipped in each release, written as prose, with the breaking parts at the top. (kind: project · also known as: releases, what changed, release notes) - [0.0.0. The scaffold](https://opsinjs.pensievelabs.org/project/changelog/2026-09-scaffold): The first release. It is a documentation site, a token layer and twenty-four component specifications, with no components. (kind: project · also known as: first release, 0.0.0, initial commit) - [Community](https://opsinjs.pensievelabs.org/project/community): Where to ask, what each channel is for, and what response you can honestly expect from a small unfunded project. (kind: project · also known as: where to ask, support, get help, discussions) - [Decisions](https://opsinjs.pensievelabs.org/project/decisions): Architecture decision records say why the system is shaped the way it is, including the choices that constrain everything built after them. (kind: project · also known as: ADR, architecture decisions, why is it like this) - [ADR 0001. Base UI, not Radix](https://opsinjs.pensievelabs.org/project/decisions/0001-base-ui-not-radix): The primitive layer is Base UI everywhere, chosen for its animation contract and for keeping exactly one primitive library in the tree. (kind: project · also known as: why base ui, radix, primitives) - [ADR 0002. Distribute as a shadcn registry](https://opsinjs.pensievelabs.org/project/decisions/0002-shadcn-registry-distribution): Ship components as copyable source through a shadcn-spec registry, and do not build a CLI first. (kind: project · also known as: why not npm, registry distribution, copy paste components) - [ADR 0003. Two colour axes that never mix](https://opsinjs.pensievelabs.org/project/decisions/0003-two-colour-axes): Category identity and clinical status are independent colour systems, and no element may carry both. (kind: project · also known as: why two axes, never mix, colour architecture) - [ADR 0004. lyra themes the documentation chrome only](https://opsinjs.pensievelabs.org/project/decisions/0004-lyra-docs-chrome): This site looks deliberately unlike the system it documents, and every preview renders under the product theme in its own scope. (kind: project · also known as: why does the site look like this, lyra decision, chrome versus product) - [ADR 0005. No [lang] segment yet](https://opsinjs.pensievelabs.org/project/decisions/0005-no-lang-segment-yet): Internationalisation is deferred deliberately, the retrofit is bounded by routing through one module, and unit systems ship now as a correctness feature. (kind: project · also known as: i18n, localisation, translations, lang segment) - [ADR 0006. Generated, never authored](https://opsinjs.pensievelabs.org/project/decisions/0006-generated-not-authored): Source code, tables and every measured number are produced by scripts, committed as MDX, and checked for drift in CI. (kind: project · also known as: generated docs, why is this table empty, drift check) - [ADR 0007. Two root layouts, and no app/layout.tsx](https://opsinjs.pensievelabs.org/project/decisions/0007-two-root-layouts): The isolated preview surface owns its own document, so the application has two sibling root layouts and no shared one. That is awkward for the 404 page. (kind: project · also known as: root layout, view routes, isolated preview, 404 page) - [ADR 0009. The default export is a demo, not the component](https://opsinjs.pensievelabs.org/project/decisions/0009-default-export-is-a-demo): Every registry file exports a named component with its real required props and a separate zero-argument demo as its default export. (kind: project · also known as: default export, demo export, zero prop demo, why two exports) - [ADR 0010. Shared code ships inside every registry item](https://opsinjs.pensievelabs.org/project/decisions/0010-shared-code-ships-with-every-item): One substrate module, appended to every component's files list with its real content, so the same import path resolves in this repository and in a consumer's. (kind: project · also known as: shared code, substrate module, lib opsinjs, shared module) - [ADR 0011. Anatomy parts are structure, not a public API](https://opsinjs.pensievelabs.org/project/decisions/0011-anatomy-parts-are-data-slots): The part tree in every specification is the DOM contract expressed as data-slot, not exported compound components, and the attribute vocabulary is four names. (kind: project · also known as: anatomy parts, data-slot, compound components, part names) - [ADR 0012. Example data is synthetic and explicitly unsourced](https://opsinjs.pensievelabs.org/project/decisions/0012-synthetic-example-data): Every demo and preview uses obviously invented numbers and one shared literal in place of a source, because a plausible example range is a fabricated citation. (kind: project · also known as: example data, synthetic data, example source, unsourced example) - [ADR 0013. A component preview is an iframe, not an inline render](https://opsinjs.pensievelabs.org/project/decisions/0013-previews-are-iframes): Every component preview embeds a /view route in a frame, because the two palettes overlap and an inline preview shows a component that is not the component. (kind: project · also known as: preview iframe, inline preview, preview isolation) - [ADR 0014. The material rung names are the token names](https://opsinjs.pensievelabs.org/project/decisions/0014-material-rung-names): Three documents name the six material rungs three ways. The names in tokens/material.json win, because a stylesheet resolves them and a drift gate checks them. (kind: project · also known as: material rung names, rung names, canvas card raised) - [ADR 0015. Error codes are flat, not banded](https://opsinjs.pensievelabs.org/project/decisions/0015-error-codes-are-flat): OPSIN-0001 upwards, allocated in sequence with no meaningful ranges. tokens/errors.json is the only place a code is authored, and the rest is generated from it. (kind: project · also known as: error code ranges, why not OPSIN-01xx, flat error codes, code numbering) - [ADR 0016. The unit table ships spoken forms, not conversion factors](https://opsinjs.pensievelabs.org/project/decisions/0016-the-unit-table-ships-no-factors): An authored token source that says what a number is measured in and how to say it aloud, and refuses by name the three conversions that are not definitions. (kind: project · also known as: unit table, units json, conversion factors, spoken units, mmol mg/dL) - [ADR 0017. precision means decimal places, everywhere](https://opsinjs.pensievelabs.org/project/decisions/0017-precision-means-decimal-places): One name, one meaning, taken from the measurement rather than the unit. It is never significant figures, which would make one metric change shape as it moves. (kind: project · also known as: why precision is decimal places, precision prop, one precision meaning) - [ADR 0021. A modal surface owns its own open state](https://opsinjs.pensievelabs.org/project/decisions/0021-modal-surfaces-own-their-open-state): Sheet and Dialog declare open and onOpenChange, anything extending them inherits both, and a dialog never quietly becomes a sheet. (kind: project · also known as: open state, onOpenChange, sheetBelow, extends sheet, modal ownership) - [ADR 0023. Three release phases, and only a component page carries one](https://opsinjs.pensievelabs.org/project/decisions/0023-three-release-phases): The phase vocabulary becomes planned, shipped and deprecated, and status leaves every page that is not a component. Four of the six old words described nothing. (kind: project · also known as: three release phases, planned shipped deprecated, why alpha was removed, why beta was removed, why status left the documentation pages) - [ADR 0024. The component page is lean](https://opsinjs.pensievelabs.org/project/decisions/0024-the-component-page-is-lean): A component page drops from seventeen sections to fourteen, and the build holds its body to a thousand words, because nobody was reading the nine thousand. (kind: project · also known as: why the component pages got shorter, word budget, ADR 0024) - [ADR 0025. The WCAG 2.2 AA audit is author-run](https://opsinjs.pensievelabs.org/project/decisions/0025-the-audit-is-author-run): Every component was audited against WCAG 2.2 AA and the findings fixed. Auditing your own work is not independent review, and clinical review is still pending. (kind: project · also known as: author-run audit, WCAG 2.2 AA audit, the components were audited, ADR 0025) - [Deprecations](https://opsinjs.pensievelabs.org/project/deprecations): The live list of what is going away, what replaces it, when it was deprecated and when it will be removed. (kind: project · also known as: removed, deprecated api, what is going away) - [Docs freshness](https://opsinjs.pensievelabs.org/project/docs-freshness): Every page has a review cadence and a reviewer discipline. An expired page is reported by CI, not discovered by a reader. (kind: project · also known as: review cadence, stale docs, out of date pages) - [Licence and attribution](https://opsinjs.pensievelabs.org/project/licence-and-attribution): The code is MIT and the guidance prose is separately CC BY 4.0, so a team can quote this guidance inside a clinical safety case with a clear attribution path. (kind: project · also known as: licence, license, MIT, CC BY 4.0, how to cite, can I use this) - [Official resources](https://opsinjs.pensievelabs.org/project/official-resources): The canonical domain, npm scope, registry URL and repository, with the way to tell this project from something impersonating it. (kind: project · also known as: canonical domain, npm scope, impersonation, is this the real opsinjs) - [Release phases](https://opsinjs.pensievelabs.org/project/release-phases): The three statuses are planned, shipped and deprecated, with exactly what each one promises and what none of them promises. (kind: project · also known as: status badge meaning, what planned means, what shipped means, phases) - [Roadmap](https://opsinjs.pensievelabs.org/project/roadmap): The public backlog is ordered, shows its blockers, and deliberately has no dates. (kind: project · also known as: backlog, what is next, when will X ship) - [Security](https://opsinjs.pensievelabs.org/project/security): How to report a vulnerability, what counts as one in a system distributed as copied source, and where the advisories are published. (kind: project · also known as: vulnerability, responsible disclosure, report a security issue) - [State of the system](https://opsinjs.pensievelabs.org/project/state-of-the-system): Dated and blunt about what exists today, what is safe to build on, what will break, and who is behind it. (kind: project · also known as: what exists, is it ready, production ready, current state) - [Versioning policy](https://opsinjs.pensievelabs.org/project/versioning-policy): What counts as a breaking change. It includes the rendered DOM, the data-* attributes and the CSS custom properties, not only the JavaScript API. (kind: project · also known as: semver, breaking change policy, upgrade safety, migration guide, breaking change guide) ## Other pages Pages that do not sit under one of the sixteen documentation groups. - [Packages](https://opsinjs.pensievelabs.org/packages): Five npm packages sit alongside the copy-paste registry, for the jobs that copied source cannot do. None of them has shipped yet. (kind: guide · also known as: npm packages, opsinjs packages, published library, package list) - [@opsinjs/color](https://opsinjs.pensievelabs.org/packages/opsinjs-color): The colour engine as a callable API, covering OKLCH, gamut mapping, APCA and WCAG 2.2, and deriveTheme(). The check that gates this site can gate your CI too. (kind: guide · also known as: deriveTheme, apca function, oklch library) - [@opsinjs/motion](https://opsinjs.pensievelabs.org/packages/opsinjs-motion): Spring solving and CSS linear() generation as a callable API, plus the reduced-motion contract expressed as code rather than as advice. (kind: guide · also known as: spring solver, linear() generator, motion library, easing maths) - [@opsinjs/preset](https://opsinjs.pensievelabs.org/packages/opsinjs-preset): The Tailwind theme layer as an importable preset, so many applications can share one token vocabulary without copying a stylesheet into each of them. (kind: guide · also known as: tailwind preset, shared theme, monorepo theme, theme package) - [@opsinjs/react](https://opsinjs.pensievelabs.org/packages/opsinjs-react): The components as a conventional npm dependency, for teams that cannot vendor source. The trade is stated plainly before you take it. (kind: guide · also known as: react package, npm components, not copy paste, library install) - [@opsinjs/tailwind.css](https://opsinjs.pensievelabs.org/packages/opsinjs-tailwind-css): The opsinjs stylesheet as a versioned import, carrying token values, preference degradations, the base layer and the dark variant, in the one order that works. (kind: guide · also known as: stylesheet package, token css, opsinjs css import, base layer)