opsinjs
HealthNumbers on a screen

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.

What this means

From two readings a week apart, an interface is entitled to say that the second is higher than the first, and that is the whole of what it knows. It may not say the metric is rising, because two points do not establish a direction. It may not say the change is meaningful, because it does not know the measurement error. It may not say the change is worse, because whether a higher value is better or worse depends on the metric, the person, and what they are trying to do.

Trend surfaces fail in one direction, towards a confident narrative, and that is this page's position rather than a measured finding. A coloured arrow is cheap to build and reads well in review, and it stacks four separate assertions into one glyph where none of them is stated and none is checkable. The first assertion is that the change is real and not measurement variation. The second is that two readings establish a direction. The third is that the direction is better rather than worse. The fourth is that the change is about the reader and not about the circumstances in which the measurement was taken.

The second failure attracts less attention and is the one rules 4 and 7 are aimed at. Weight, blood pressure, resting heart rate and sleep all fluctuate day to day for reasons unconnected to health. Hydration, the time of the measurement, the cuff position and a warm room are among them. An interface that changes status in response to that variation teaches the reader to treat variation as significant, and the cost of that lesson falls due on the reading where the movement is not variation, because by then the reader has no way to tell the two apart.

The rule

Separate direction from valence, require a minimum window before drawing a trend at all, and never let noise cross into status.

Ten requirements follow, and their numbering is cited further down the page. The What the component must be given column names the input each one needs, and the Who owns that value column records where that input comes from. opsinjs supplies none of the clinical values listed there.

#RequirementWhat the component must be givenWho owns that valueFailure it prevents
1Direction and valence are two different pieces of information. Direction (up, down, unchanged) is arithmetic, and valence (better, worse, neutral) is a clinical judgement about a specific metric for a specific person that is frequently unavailable.The two values being compared, and the valence mapping for the metric where one exists.Direction needs no owner. The valence mapping belongs to the metric's clinical owner.An arithmetic fact presented to the reader as a judgement about their health.
2Where valence is unknown, the surface shows direction only. The arrow carries no colour, no status and no adjective.Whether a valence is defined for this metric, stated rather than inferred from an absent value.The metric's clinical owner, who either defines the mapping or declines to.A green arrow reporting a fall in a number for which falling has not been judged better.
3A metric declares its minimum window, and no trend is drawn below it. Two readings establish a difference between two values and not a direction.The metric's minimum window, as a required input rather than an optional one.The metric's clinical owner. opsinjs publishes no windows.A line through too few points, which a reader reads as a trajectory.
4A metric declares a change threshold, and a difference below it is presented as unchanged. "About the same as last week" is the true statement below the noise floor.The metric's change threshold, as a required input rather than an optional one.The metric's clinical owner. opsinjs publishes no thresholds.Day-to-day measurement variation rendered to the reader as a change.
5The comparison is named on screen. "Compared with your average over the last 4 weeks" names its baseline, and a bare delta against an unnamed baseline does not.The baseline and the window it covers, in the wording shown to the reader.The product, which chooses the baseline.A difference the reader cannot interpret because they cannot see what it was measured against.
6The time axis is honest. Irregular readings are plotted at their real positions, gaps are visible as gaps, and the axis is never truncated to exaggerate a slope. See Chart anatomy.Each reading's own timestamp, rather than its index in the series.The data source.A slope produced by the axis rather than by the readings.
7A trend never sets a status on its own. A direction may raise the salience of a value, and the status still comes from the value against its range. Rising inside the usual range is not attention.The latest value and its range, which are the only inputs to status.The metric's clinical owner, who supplies the range.An attention status raised by movement that never left the usual range.
8The surface never extrapolates. No projected line, no "at this rate" wording and no predicted value is rendered.Observed readings only, with no future positions on the axis.A projection read as a measurement once its uncertainty band has been dropped.
9Every chart ships a text twin, so the trend is readable as a sentence by a screen reader and by readers who do not read charts. See Accessible charts.The sentence itself, built from the same baseline, window and direction as the chart.The product, which writes the wording.A trend available only to a reader who can see a chart and interpret it.
10Absence is rendered as absence. Missing readings are drawn as missing, are never interpolated and are never plotted as zero.Which positions in the series hold no reading.The data source.Readings that were never taken appearing in the reader's own history.

Why (evidence)

Applying it

Do

"About the same as your average over the last 4 weeks." The sentence names the baseline and the window, and it reports a difference below the metric's change threshold as no change.

Don’t

Show "▲ 2%" with no baseline and no window, coloured green because a rise is better for this metric in general. The colour asserts a valence for this reader that the product has not established, and the figure is a difference against a baseline the reader cannot see.

Do

"You have 2 readings. Log a few more over the next couple of weeks and we can show you how this is changing." The state reports how many readings exist and what would make a trend renderable.

Don’t

Draw a line between two points and label it "Trending up". A line through two points asserts a direction that two readings cannot establish, and the label restates that assertion as a finding.

Do

Keep the status pill driven by the latest value against its range, and let the sparkline carry the direction separately. Each surface then reports one thing, and a reader can watch the direction move without the status moving with it.

Don’t

Escalate to attention because three readings went up while all three sat inside the usual range. The escalation rests on movement within measurement variation rather than on any value crossing its range, which is the case rule 7 excludes.

Do

Show the gap: "No readings between 3 and 17 March." The sentence gives the reader the dates over which the series has nothing to report.

Don’t

Connect across the gap with a straight line. The interpolated segment draws two weeks of readings that were never taken, at values no instrument produced.

Components that implement this

TrendSparkline is specified to take a minimum window and a change threshold as required inputs rather than optional ones, so a caller cannot obtain a trend by omission, and to render an explicit not-enough-data state instead of a two-point line. Both values arrive from the caller, because opsinjs holds neither of them.

What this does not cover

  • Minimum windows and change thresholds for any metric. These are clinical content and belong to the implementing team.
  • Statistical smoothing, seasonality and time-series modelling. Where the implementing team smooths a series, the raw points must remain visible to the reader.
  • Chart construction, axes and colour, which are Data visualisation.
  • The pattern for a whole trend review screen, which is Trend review.
  • Goals and targets. A target is a valence the reader chose, which changes the analysis and is not yet specified here.

Updates to this page

Last read through against the system on 2026-09-02. Due for review every 12 months; expiry is reported by pnpm run check:freshness.

On this page