Not a medical device and not for clinical use. These components are reference implementations for developers. Clinical rules are cited so you can check them, not so you can rely on them.
React components that take HL7® FHIR® R4 resources as props and render them by the clinical rules they cite.
Each component installs on its own with the shadcn CLI, into a React project with Tailwind and the shadcn cn helper:
npx shadcn@latest add https://raw.githubusercontent.com/Henrycarto/wardkit/main/public/r/lab-result.json
npx shadcn@latest add https://raw.githubusercontent.com/Henrycarto/wardkit/main/public/r/vitals-trend.json
npx shadcn@latest add https://raw.githubusercontent.com/Henrycarto/wardkit/main/public/r/news2-panel.json
npx shadcn@latest add https://raw.githubusercontent.com/Henrycarto/wardkit/main/public/r/allergy-banner.json
npx shadcn@latest add https://raw.githubusercontent.com/Henrycarto/wardkit/main/public/r/patient-banner.jsonFiles land in components/wardkit/ and lib/wardkit/, plus shadcn's lib/utils.ts (the cn() helper) if the project does not have one yet. Packages a component adds: lucide-react (icons) and cn (installed by shadcn's utils item; checked with shadcn 4.22 on Tailwind v4), and @types/fhir as a dev dependency. React is expected to be there already. Charts are plain SVG.
import type { Observation } from 'fhir/r4';
import { LabResult } from '@/components/wardkit/lab-result';
const potassium: Observation = {
resourceType: 'Observation',
status: 'final',
code: { coding: [{ system: 'http://loinc.org', code: '2823-3', display: 'Potassium [Moles/volume] in Serum or Plasma' }], text: 'Potassium' },
effectiveDateTime: '2026-10-21T00:40:00+02:00',
valueQuantity: { value: 6.9, unit: 'mmol/L', system: 'http://unitsofmeasure.org', code: 'mmol/L' },
interpretation: [{ coding: [{ system: 'http://terminology.hl7.org/CodeSystem/v3-ObservationInterpretation', code: 'HH' }] }],
referenceRange: [{ low: { value: 3.5, unit: 'mmol/L' }, high: { value: 5.1, unit: 'mmol/L' } }],
};
export default function Result() {
return <LabResult observation={potassium} timeZone="Europe/Vienna" />;
}This renders "6.9 mmol/L" with a "Critically high" flag (text and icon, not only colour) and the range "3.5 to 5.1 mmol/L".
| Component | Takes | Rule it enforces |
|---|---|---|
LabResult |
Observation |
The flag comes only from interpretation (H, L, HH, LL, A, N). preliminary is marked, amended and corrected are marked as changed, entered-in-error is never shown as a valid result, and a dataAbsentReason is shown in place of a value, never a blank or a zero. Values in component (blood pressure panels, LOINC 85354-9) are shown per component by the same rules. |
VitalsTrend |
Observation[] |
A missing reading, a dataAbsentReason or an entered-in-error reading breaks the line into a visible gap. Nothing is interpolated across a gap. Mixed codes or units are refused. |
News2Panel |
Observation[] |
NEWS2 (RCP 2017) from the latest reading of each parameter, read by LOINC code. A missing, stale or unreadable parameter makes the score incomplete and is named. Never scored from a guessed value; room air is never assumed. SpO2 scale 2 only when the caller turns it on. Rounded values are shown next to what was recorded. |
AllergyBanner |
AllergyIntolerance[] |
"No known allergies" only when a resource records it with a no-known code (SNOMED CT 716186003 and the six concepts under it, or the IPS absent-unknown codes). An empty list shows "No allergy information recorded", which looks different. entered-in-error is hidden, refuted is not shown as an allergy. |
PatientBanner |
Patient |
Uses the official name. Shows date of birth with age, administrative gender and the main identifier with its system. Handles a missing or partial birth date and a deceased patient (deceasedBoolean or deceasedDateTime). |
Every component page on the docs site has a live example, the props, and each rule with its source. The NEWS2 page lists every LOINC code read; the allergy page lists every no-known code.
- Royal College of Physicians. National Early Warning Score (NEWS) 2. 2017.
- HL7 FHIR R4: Observation, Vital signs profiles, AllergyIntolerance, Patient.
- HL7 Terminology: v3 ObservationInterpretation, DataAbsentReason.
- HL7 International Patient Summary: Allergies and Intolerances value set, 2.0.1 and Absent or Unknown Allergies, 1.1.0.
- LOINC 2.82 and SNOMED CT International 2025-02-01, codes checked through the HL7 terminology server (tx.fhir.org).
HL7, FHIR and the FHIR [FLAME DESIGN] are the registered trademarks of Health Level Seven International and their use does not constitute endorsement by HL7.
npm install
npm test # Vitest + Testing Library, axe on every component
npm run test:a11y # axe in Chromium on every docs page, light and dark, desktop and phone (needs npm run build)
npm run validate:fixtures # official HL7 validator 7.0.2 on every fixture (needs Java 17+)
npm run typecheck
npm run lintEach clinical rule above has its own test: every NEWS2 band boundary and risk band, each interpretation code, each status, gap handling, the difference between "no known allergies" and "not recorded", and a deceased patient. The fixtures in fixtures/ are hand-written synthetic FHIR R4 resources; every patient in them is fictional. CI runs all of the above, plus the registry build and the docs build.
- Trailing zeros can be lost. FHIR decimals carry their precision: a value or range limit of 2.0 is not the same as 2.
JSON.parseturns both into the JavaScript number 2, so the components display "2" where the resource said "2.0". Keeping the precision would need the original JSON text or a decimal-preserving parser; the components do not do that yet.
npm run devMIT
