Skip to content
OX / 01Build on meaning

FHIR R4 · source-first · MIT core

Healthcare UI that already knows what the data means.

Pass a FHIR Observation[] and get reference ranges, interpretation flags, and the uninterpreted case handled correctly. The source is copied into your repo — yours to read, audit, and change.

pnpm dlx shadcn@latest add @oxygenui/vitals-panel
Browse components
Source copiedWCAG-mindedRuntime: 0
Typed to
PatientObservationMedicationRequestAllergyIntoleranceAppointmentConditionCoverage
Live components · synthetic data

Okonkwo, Amara

MRN
093-441-208
DOB
1984-03-17 (42y)
Sex
female
Results
TestResultReferenceInterpretation
Heart rate
72 beats/min60 – 100 beats/minNormal
Hemoglobin
10.2 g/dL12 – 15.5 g/dLLow
Ferritin
43 ng/mLNot interpreted

Everything present and interpreted. The easy case — and the only one most libraries ship.

Density

Why this exists

The states your demo skips are the states your users hit.

A generic card renders a value. It has no opinion about a result that came back preliminary, a range that doesn’t exist, a record flagged restricted, or a potassium of 6.8. Those aren’t edge cases. They are Tuesday.

01 / RESULT PROTOCOL
0
STATES

Result states per component

Final, preliminary, corrected, amended, critical, absent, uninterpreted.

02 / LAYOUT SYSTEM
0
MODES

Density modes

Patient-facing, standard admin, and clinical-dense — switchable at any container.

03 / SOURCE RUNTIME
0
ADDED

Runtime dependencies added

The components are source. Nothing sits between you and the render.

The difference

Same five results. Two renderers.

Not a feature list — the actual output. The left panel is written the way the hand-rolled example in our docs is written, and every defect it produces follows directly from that code.

Hand-rolledsame data, both panels
5 results · 5 defects
  • Blood pressure reads “undefined undefined” — its value lives in Observation.component, not on the parent.
  • A hemolysed specimen renders as Normal instead of stating its dataAbsentReason.
  • Ferritin has no reference range, so it is labelled Normal. Nothing interpreted it.
  • A stated critical potassium is flattened to “High”, with no escalation at all.
  • A preliminary TSH is presented as though it were final.
Oxygenone component
5 results · 0 defects

1 critical result in this panel.

Oxygen rendering of the same data
TestResultReferenceInterpretation
Potassium
6.8 mmol/L3.5 – 5.1 mmol/LCritical high
Blood pressure
2 partsHigh
Systolic168 mmHg90 – 130 mmHgHigh
Diastolic82 mmHg60 – 85 mmHgNormal
Ferritin
43 ng/mLNot interpreted
White blood cell count
White blood cell count, Not knownSpecimen hemolyzed — recollectNot interpreted
TSH
Preliminary
5.9 mIU/L0.4 – 4 mIU/LHigh

Blood pressure resolves to its components and escalates to the worst of them. The absent result states why. Ferritin reads Not interpreted, never Normal. The critical potassium carries a badge, a rule, and a live-region announcement — and preliminary stays labelled preliminary.

Catalog

Every component is named for the resource it takes.

No adapter layer, no bespoke prop shape to learn. If your server speaks FHIR, the component is already typed for it.

Start here

Absent Value

Stable

dataAbsentReason

Renders absence as a statement. Withheld, not asked, declined, and errored are different facts and never share a dash.

7 statesView

Action Gate

Stable

AuditEvent

Two-step confirmation that names the consequence and the patient, then emits an audit event.

6 statesView

Alert Banner

Stable

DetectedIssue

Severity tiers as an interruption budget. Only critical may take focus.

6 statesView

Allergy List

Stable

AllergyIntolerance

Criticality and verification status, with no-known-allergies as its own state.

8 statesView

App Shell

Stable

PractitionerRole

Navigation composed from permissions, patient context as a landmark, and guarded context changes.

6 statesView

Appointment Card

Stable

Appointment

Booked, pending, cancelled, no-show. Time zone is a required prop, not a guess.

10 statesView

Care Team Panel

Stable

CareTeam

Everyone involved, and who is actually reachable now.

6 statesView

Clinical Skeleton

Stable

Loading shaped like layout, never like a value — plus progressive sections that keep partial failure visible.

5 statesView

Clinical Time

Stable

dateTime · instant

A clinical instant with a required time zone, honouring FHIR partial-date precision.

7 statesView

Clinical Value

Stable

Quantity

One measured quantity, unit, and comparator as a single atomic element that cannot drift apart.

6 statesView

Code Status

Stable

Consent

Resuscitation status and directives. Unknown is loud, never a silent default to full code.

7 statesView

Concept Chip

Stable

CodeableConcept

A coded concept with its coding one interaction away, and honest about what is missing.

6 statesView

Condition List

Stable

Condition

Problem list that separates active from resolved and never promotes a provisional diagnosis.

9 statesView

Coverage Card

Stable

Coverage

Effective state derived from status and period together — an active record past its end date reads as lapsed.

6 statesView

Density Provider

Stable

Sets the spacing and target-size contract for a subtree. Density changes spacing, never which facts appear.

5 statesView

Dose Input

Stable

Dosage

Dose entry with ISMP formatting rules, plausibility separated from hard limits, and visible arithmetic.

7 statesView

Empty State

Stable

Five reasons a section shows nothing. An unavailable section is never rendered as an empty one.

6 statesView

Error Boundary

Stable

OperationOutcome

Contains a failure to one section and never renders a partial record as a complete one.

4 statesView

Identity Token

Stable

Patient

Compact, privacy-aware representation of a person, built around confirming rather than labelling.

7 statesView

Medication Card

Stable

MedicationRequest

Dose, route, schedule, and status. Held, stopped, and expired are distinct — not one greyed-out style.

9 statesView

Patient Banner

Stable

Patient

Persistent identity header for a clinical screen, driven by a FHIR Patient resource.

6 statesView

Patient Snapshot

Stable

Composition

One-screen pre-encounter summary where every section carries its own recency and failure.

6 statesView

Precautions Bar

Stable

Flag

What staff must do before entering the room, ordered by required action.

7 statesView

Provenance Tag

Stable

Provenance

Who recorded this, when, from where, and whether it has been amended.

7 statesView

Reference Range

Stable

Observation.referenceRange

Positions a result against its own range, and refuses to draw when no bound was stated.

6 statesView

Restricted Shield

Stable

Consent · meta.security

Redacted by default. Discloses only with a stated reason, on a timer, and can conceal that content exists.

6 statesView

Status Badge

Stable

The shared severity chip. Critical reads identically on a lab result, a medication, and an allergy.

6 statesView

Unsaved Guard

Stable

Stops clinical documentation being lost to a navigation, a patient switch, or a closed tab.

7 statesView

Observation Panel

Stable

Observation[]

Results table with reference ranges and interpretation. Uninterpreted results stay uninterpreted.

10 statesView

Quality

Claims we are willing to be held to.

Accessibility, stated as a target
WCAG 2.2 AA is the bar, and it is enforced in CI — every page is audited with axe-core in both light and dark on each commit. That check found and fixed four real violations, three of them in the clinical status tokens themselves. Automated testing catches roughly a third of WCAG issues, so keyboard and screen-reader passes remain manual.
Status is never color alone
Every severity carries an icon, a text label, and a second structural cue. View any component in forced-colors mode: nothing that mattered disappears.
Synthetic data, always
Every fixture, demo, and screenshot uses invented values on reserved example.org systems. No PHI enters this repository, its issues, or its analytics.
What this is not
Oxygen is not a compliance boundary. It does not make an application HIPAA, GDPR, or DPDP compliant, and it is not a medical device. It is well-built UI; the clinical and regulatory obligations remain yours.

Install one component. See if it holds up.

The core is MIT. Nothing is gated behind an account, and the source lands in your repository where you can read every line before you trust it.

pnpm dlx shadcn@latest add @oxygenui/vitals-panel

@oxygenui is a shadcn registry namespace — add "@oxygenui": "https://oxygenui.design/r/{name}.json" to your components.json once, or pass the full URL instead.