Foundations

Icons

One library, one weight, and a documented job for every glyph. This page also names the symbols this system will not use, and says why.

opsinjs uses lucide and nothing else. One library means one stroke weight, one optical size and one set of metaphors; two libraries means two warning triangles on the same screen, drawn slightly differently, and a reader who has to work out whether the difference means something.

Icons here are documented the way components are: each one has a job written next to it. An icon without a stated job gets used for whatever it looks like, which is how a stethoscope ends up labelling a settings screen.

The rule that matters most: an icon never carries clinical status on its own. Status is a word, a shape and a colour together. Somebody using a screen reader gets the word; somebody printing the page in greyscale gets the shape; somebody glancing at it in sunlight gets the colour. Any one of those failing must not take the meaning with it.

Related


53 of 53

Status

One glyph per clinical status level, declared once in lib/status.ts and never chosen per component. What separates the four is the ordinal weight of the silhouette rather than membership of one family: a plain circle, then a circle with a centre, then a diamond, then an octagon, each heavier than the last, so the order of the levels survives greyscale, holds at 16 pixels, and reaches somebody who cannot separate red from green. An icon never carries status on its own. It always appears with the word.

  • CircleSteady. This reading is where it is expected to be.
  • CircleDotWatch. This reading is outside your usual range. On its own that is not unusual, and there is nothing to do before your next reading.
  • DiamondNeeds attention. Contact your care team about this reading. It is outside the range they set for you.
  • OctagonUrgent. Contact your urgent care service now. Tell them this reading and when you took it.
  • MinusNot known. The absence of a verdict, and never a fifth status level.
  • InfoContext and explanation. Never a verdict.
  • CircleQuestionMarkA definition or a glossary term.

Trend and direction

Direction only. Whether a direction is good news depends entirely on the measurement, because a falling weight and a falling blood oxygen are not the same story. These glyphs therefore never take a status colour by default. The valence comes from the status axis, applied deliberately.

  • TrendingUpRising over the window shown.
  • TrendingDownFalling over the window shown.
  • MinusNo meaningful change. That is not the same as no data. Minus is also the not-known glyph above; the surrounding label is what separates them.
  • ArrowUpA single reading higher than the last.
  • ArrowDownA single reading lower than the last.
  • MoveRightProgression through a range or a flow.

Measurement categories

Identity glyphs, paired with the category colour axis. They label what a number is, never how worrying it is. Note what is absent: there is no glyph here that depicts a clinician, a clinical instrument or a medical institution.

  • HeartCardiovascular measurements in general.
  • HeartPulseHeart rate and rhythm specifically.
  • ActivityMovement, active minutes, exertion.
  • DropletBlood glucose and other fluid measures.
  • ThermometerBody temperature.
  • WindRespiratory measures such as peak flow and breathing.
  • ScaleWeight.
  • RulerHeight, waist, any linear measurement.
  • FootprintsSteps and distance.
  • MoonSleep.
  • BrainMood, cognition, mental wellbeing.
  • PillA dose of medication, taken or due.

Time and recency

How old a reading is, is part of what the reading means. A three-day-old measurement presented as current is a safety problem, so recency gets glyphs of its own rather than being left to small grey text.

  • ClockA time of day, or a relative timestamp.
  • CalendarA date, or a logging streak.
  • CalendarClockA repeat, a review, anything scheduled.
  • RotateCcwHistory: previous readings for this measure.

Data states

Empty, loading, error, stale and partial are defined once for every data surface, and each has a glyph. Rendering “we do not know” honestly is a requirement in a health interface, not a polish item.

  • CircleDashedEmpty. Nothing recorded yet.
  • LoaderCircleLoading. The only glyph here that may spin.
  • RefreshCwStale. The value was last synced some time ago. Retry available.
  • CloudOffNot synced. The value shown is local.
  • WifiOffOffline. Nothing new can arrive right now.
  • CircleSlashPartial. Some of this record is missing.

Privacy, consent and disclosure

These screens are read in waiting rooms, on trains and over shoulders. Hiding a value, re-authenticating and recording consent are first-class interactions here rather than settings-screen afterthoughts.

  • EyeReveal a value that is hidden by default.
  • EyeOffHide sensitive values on this screen.
  • LockRe-authentication required.
  • ShieldCheckA recorded, revocable consent. Never a security claim.
  • FileTextA document: a policy, a result letter, an export.

Actions and navigation

The ordinary furniture. Included because a system that documents only its exotic glyphs leaves the everyday ones to be chosen at random, and a chevron that points a different way on two screens is a real, small, constant cost.

  • PlusAdd a reading, start a log entry.
  • CheckConfirm. Not a status.
  • XDismiss or close. Not a failure.
  • ChevronRightNavigate into detail.
  • ChevronDownExpand in place.
  • SearchSearch.
  • FunnelFilter a list of readings.
  • CopyCopy a value or a record.
  • Share2Share with somebody. The recipient is often a clinician.
  • DownloadExport. Usually the whole record, dated.
  • SettingsPreferences, units, reminders.
  • BellA reminder is on.
  • BellOffReminders are off. Say so explicitly.

Symbols this system will not use

Not a matter of taste. Each of these makes a claim about authority, provenance or institutional identity that a consumer health app is not entitled to make, and a reader who believes the claim will act on the screen differently.

  • The red cross on white

    A protected emblem under the Geneva Conventions and the national legislation implementing them. Using it decoratively is not merely misleading about who is speaking; it is a misuse of a protected sign.

    Instead: Use the status glyphs. Urgency is expressed by the status axis, not by borrowing an emergency organisation's identity.

  • The caduceus and the Rod of Asclepius

    They read as “a doctor is telling you this”. The whole safety position of a consumer health product is that it is not a clinician and does not diagnose; an icon that says otherwise undoes a paragraph of careful wording.

    Instead: Use a category glyph for what the measurement is, and a Term or CareCard for who is actually speaking.

  • Stethoscopes, white coats, clipboards with ticks

    Clinical-authority props. They shift a reading from “here is your number” to “this has been reviewed”, which is a claim about a workflow that did not happen.

    Instead: If a value genuinely has been reviewed by a clinician, say so in words with a date and a name. That is provenance, and provenance is text.

  • Prescription and pharmacy marks

    They imply a dispensing or prescribing relationship. Medication features record what somebody says they took; they do not prescribe, and the iconography must not suggest they do.

    Instead: Use the Pill glyph for a dose record, and put the prescribing relationship in the copy where it can be qualified.

  • Heart-rate lines as decoration

    An ECG trace used as ornament on a page with no ECG data teaches readers that the trace is meaningless, which is a bad habit to build in an app that may one day show a real one.

    Instead: Use TrendSparkline where there is real data, and nothing where there is not.

Stated as guidance rather than as law: this is the opinion of this design system about the products it is for, argued from the safety position set out in safety, scope and limitations. The one exception is the protected-emblem point, which is a matter of law in most jurisdictions rather than of design.

Using these icons

Import by name from lucide-react. Every icon in this inventory is a named export, so the import is tree-shaken and you pay for the glyphs you use rather than for the library. The copy button on each card gives you the exact import line.

Size icons in the same ladder as text rather than in pixels chosen per screen, and hide decorative glyphs from assistive technology with aria-hidden. An icon that duplicates an adjacent label is noise when it is announced twice. The generated component pages carry the specific rule for each component that ships an icon.