Components / Clinical

Vital signs

Heart rate, blood pressure, SpO₂ and temperature at a glance, each checked against a normal range you can configure. Every status is written out with its own icon, so it never depends on colour.

Vital signs
Resting example
Heart rate
72bpm
Normal
Normal 60–100 bpm
Blood pressure
118/76mmHg
Normal
Normal 90–120 / 60–80 mmHg
SpO₂
98%
Normal
Normal 95–100 %
Temperature
36.8°C
Normal
Normal 36.1–37.2 °C

Original example readings and common adult ranges. Not patient data or clinical guidance.

Installation

In a project set up as in Installation, run:

bunx shadcn@4.22.1 add https://organui.com/r/vital-signs.json

Or by name: bunx shadcn@4.22.1 add @organui/vital-signs.

The source installs into your configured UI directory, along with shadcn's card if you do not have it yet. It has no client state, so it renders in Server Components too, and its icons are inline so it adds no icon library.

View registry item JSON

Usage

import { VitalSigns } from "@/components/ui/vital-signs"

export function Vitals() {
  return (
    <VitalSigns
      readings={{ heartRate: 72, systolic: 118, diastolic: 76,
        spo2: 98, temperature: 36.8 }}
      description="Measured at 09:30"
    />
  )
}

Pass the latest readings as numbers. A missing, null or non-finite value shows a dash and the status No reading. Blood pressure needs both systolic and diastolic.

Ranges and status

// Merged over adultVitalRanges, one vital at a time.
<VitalSigns
  readings={readings}
  ranges={{ spo2: { low: 88, high: 92 } }}
  vitals={["heartRate", "bloodPressure", "spo2", "respiratoryRate"]}
/>

// Temperature readings and ranges in °F.
<VitalSigns readings={{ temperature: 100.4 }} temperatureUnit="fahrenheit"
  vitals={["temperature"]} />

Defaults are common resting adult ranges, exported as adultVitalRanges: heart rate 60–100 bpm, blood pressure 90–120 / 60–80 mmHg, SpO₂ 95–100%, temperature 36.1–37.2 °C (97–99 °F) and respiratory rate 12–20 per minute. Bounds are inclusive. Override any of them with ranges for children, a patient's own targets, or your institution's protocol.

A reading below its range is Low with a down arrow, above it High with an up arrow, and inside it Normal with a check. Out-of-range cards also get bold status text and your theme's destructive colour on the border and icon. Blood pressure is high when either part is high, and the text names the part out of range, such as High systolic. Each card carries data-vital and data-status attributes for your own styling.

The same logic is exported for use elsewhere: vitalStatus, bloodPressureStatus, resolveVitalRanges and assessVital.

Customize

Set title for the heading and the region's accessible name, description for a line under it, vitals to choose and order the cards, locale for number formatting (default en-US, so server and client render the same) and className for the outer card. Cards wrap to fit their container.

A display component, not a medical device. It does not compute early warning scores, trend readings, or raise alarms, and it is not a live region: announce changes yourself if readings stream in. The default ranges are not clinically validated for any population.