---
title: "Trends and change"
description: "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."
url: "https://opsinjs.pensievelabs.org/health/trends-and-change"
source: "https://opsinjs.pensievelabs.org/health/trends-and-change.md"
section: "Health"
kind: "health"
evidence: "opinion"
reviewed: "2026-09-02"
reviewer: "design"
aliases: ["direction of change", "improving", "worsening", "delta"]
implements: ["trend-sparkline", "metric-tile", "result-card", "relative-time", "status-pill", "timeline-entry"]
---

> Elements written as `<PascalCase … />` below are opsinjs documentation
> components. Their attributes are the content: the values they render are
> generated from `tokens/*.json` and `registry/catalogue.ts` and are
> published separately at https://opsinjs.pensievelabs.org/r/index.json and under the Reference
> section.
> Nothing is missing from this page. The data simply does not live in
> the prose.

<PageTemplate kind="health" />

## What this means [#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 [#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.

| #  | Requirement                                                                                                                                                                                                                                              | What the component must be given                                                                | Who owns that value                                                                   | Failure it prevents                                                                            |
| -- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------- |
| 1  | Direction 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.                  |
| 2  | Where 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.       |
| 3  | A 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.                           |
| 4  | A 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.                           |
| 5  | The 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. |
| 6  | The 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](../foundations/data-visualisation/chart-anatomy.mdx).              | 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.                                      |
| 7  | A 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.                      |
| 8  | The 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.                 |
| 9  | Every 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](../foundations/data-visualisation/accessible-charts.mdx).                                        | 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.                       |
| 10 | Absence 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) [#why-evidence]

<ResearchNote evidence="opinion" date="2026-09-02">
  This page is opinion throughout, and it rests on the properties of measurement
  rather than on a study.

  Rules 3 and 4 are the defensible core and state one idea between them: any
  measurement has a variability, and a difference smaller than that variability
  is not a difference. Clinical practice already works this way, which is why a
  clinician measures blood pressure more than once and why weight is compared
  over weeks rather than days. The design opinion is the further insistence that
  the interface must hold the threshold and refuse to draw below it, rather than
  delegating the judgement to a reader who has no way to make it.

  The separation of direction from valence is our framing, and it gives a
  reviewer one check to run against any arrow on any screen: ask which of the two
  the arrow is claiming, and whether the product is entitled to claim it.

  We publish no minimum window and no change threshold for any metric. They are
  metric-specific, population-specific and clinical, and a plausible-looking
  default table here would be copied into products by people who assumed we
  knew.

  What would change our mind: most of this page follows from the arithmetic of
  measurement variability and would need a change in that arithmetic to move.
  Rule 8's absolute ban on extrapolation is the exception, because a
  well-calibrated projection rendered with visible uncertainty is defensible in
  principle. We ban it because the uncertainty is the first thing to be dropped
  in a redesign, and field evidence that an uncertainty band survives successive
  product redesigns intact would revise rule 8.
</ResearchNote>

## Applying it [#applying-it]

<DoDont>
  <DoDont.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.
  </DoDont.Do>

  <DoDont.Dont>
    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.
  </DoDont.Dont>
</DoDont>

<DoDont>
  <DoDont.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.
  </DoDont.Do>

  <DoDont.Dont>
    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.
  </DoDont.Dont>
</DoDont>

<DoDont>
  <DoDont.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.
  </DoDont.Do>

  <DoDont.Dont>
    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.
  </DoDont.Dont>
</DoDont>

<DoDont>
  <DoDont.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.
  </DoDont.Do>

  <DoDont.Dont>
    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.
  </DoDont.Dont>
</DoDont>

## Components that implement this [#components-that-implement-this]

{/* Generated from `implements`. Do not restate the list by hand. */}

`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 [#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](../foundations/data-visualisation/index.mdx).
* **The pattern for a whole trend review screen**, which is
  [Trend review](../patterns/trend-review.mdx).
* **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 [#updates-to-this-page]

<Reviewed />
