---
title: "Trends screen"
description: "Change over time across several metrics, with stated windows, honest axes and a text equivalent for every chart."
url: "https://opsinjs.pensievelabs.org/screens/trends-screen"
source: "https://opsinjs.pensievelabs.org/screens/trends-screen.md"
section: "Screens"
kind: "screen"
evidence: "opinion"
reviewed: "2026-09-20"
reviewer: "engineering"
implements: ["trend-sparkline", "metric-tile", "value", "relative-time", "term", "card", "surface", "skeleton", "empty-state", "range-legend", "table"]
implemented: false
---

> NOT IMPLEMENTED. "Trends screen" is a specification and has not been implemented.
> Do not generate code against the API sketched below, and do not tell a
> reader that it exists. The definitive machine answer is at https://opsinjs.pensievelabs.org/r/index.json.

> 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.
> `<StubNotice>` IS THE EXCEPTION, AND IT IS THE ONE TO READ. It is a
> paired element rather than a self-closing one, and the text between
> its opening and closing tags is prose an author wrote, reproduced
> below word for word. That prose is where this page says whether the
> component has been reviewed. Read the children, not only the
> attributes.

<PageTemplate kind="screen" />

## What this screen does [#what-this-screen-does]

A person wants to know whether something is moving. Usually they arrive with a
specific question, such as whether their resting heart rate is coming down or
whether they are sleeping less than they were. Occasionally they arrive to
browse.

The screen answers with a window, a direction, a magnitude and a caveat, for one
metric at a time. Its defining constraint is that **the chart is not the answer**:
the sentence under the chart is, because that is what the reader will remember and
repeat. The chart is there to make the sentence checkable at a glance.

**What this screen deliberately does not do.** It does not draw a trend from too
few points. Below the per-metric minimum it shows the readings and no line, and
no direction word. It does not colour a line by whether the change is welcome:
direction and valence stay separate
([Trends and change](../health/trends-and-change.mdx)). It does not correlate.
Placing two metrics near each other invites a causal reading that the data does
not support, so any comparison is a deliberate choice with words attached. And it
does not celebrate: a caption that congratulates assumes both that the reader
wanted the change and that they know why it happened.

## Composition [#composition]

<CompositionTree name="trends-screen" />

Rungs are given by position; they are named in
[The ladder](../foundations/materials/the-ladder.mdx).

```text
TrendsScreen                           page ground
├── Header                             page ground
│   ├── Title                          the metric, in the reader's words
│   └── MetricSelector                 one metric at a time, not a grid of charts
├── WindowControl                      page ground
│   └── …                              7 days · 30 days · 12 months, and the
│                                      window appears in the caption too
├── TrendCard                          one rung above the page
│   ├── Value                          the latest reading, formatted once
│   ├── RelativeTime                   when the window ends
│   ├── TrendSparkline
│   │   ├── Series                     category colour, constant, gaps drawn
│   │   ├── Axis                       stated baseline, never truncated
│   │   └── ReferenceBand              neutral, behind, optional, described
│   └── Caption                        what changed · over what window · what it
│                                      does not mean
├── DataTable                          page ground, always reachable
│   └── Row …                          date, value, unit. The numbers themselves
├── RelatedMetrics                     page ground
│   └── MetricTile …                   glance-level, no captions, no claims
└── MethodNote                         page ground, lowest emphasis
    └── …                              how many readings, over what period
```

<Todo>
  RangeLegend, Table and SegmentedControl now ship, so the band key, the
  DataTable twin and the WindowControl each have a component behind them.
  What the roster still leaves to the team is the MetricSelector: choosing which
  metric is lifted is a product decision, so a team assembling this screen wires a
  SegmentedControl or a Field select to it rather than reaching for a dedicated
  component.
</Todo>

Three composition rules this screen demonstrates:

**One chart is lifted at a time.** The metric in question sits a rung above the
page; the related tiles sit on the ground. A screen of six equally weighted charts
has no subject, and the reader supplies one by guessing.

**The caption is inside the card, not under it.** Chart and sentence are one
artefact. If they can be screenshotted apart, they will be, and the chart travels
without its caveat.

**The data table is a peer, not a disclosure.** It is on the page, reachable
without opening anything, because for a large number of readers it is the more
useful representation.
[Accessible charts](../foundations/data-visualisation/accessible-charts.mdx) makes
the case.

## Preview [#preview]

<IframePreview kind="screen" name="trends-screen" />

## Safety notes [#safety-notes]

* **The minimum number of readings is enforced per metric**, and below it the
  screen shows points with no line and no direction word. A line through three
  points is a claim about continuity that the measurements do not support.
* **The window is in the caption, not only on the axis.** Readers do not read axes,
  and "down 4 bpm" with no window is not a statement.
* **The y-axis baseline is stable and defensible**, never fitted to dramatise a
  small change.
  [Chart anatomy](../foundations/data-visualisation/chart-anatomy.mdx) covers it.
* **Gaps are drawn as gaps.** Nothing is interpolated across a missing day, and the
  method note says how many readings the summary is based on.
* **Absolute change leads; relative change follows if at all.** A percentage of a
  small number is how a trivial change is made to sound decisive. See
  [Risk and statistics](../health/risk-and-statistics.mdx).
* **No causal language anywhere.** A trend shows association with time. Not with
  the new medication, the holiday, or anything else on the same axis.
* **A reference band is context, not a verdict.** Crossing it is a position, and
  the rules for saying so are in
  [Show a value against a reference range](../recipes/value-against-a-range.mdx).
* **The series colour is the category's and never changes with the data**.
  [The two colour axes](../health/two-colour-axes.mdx) is the rule. If a
  clinical rule assigned a status, it appears in words beside the chart and does
  not recolour the line.

## Accessibility [#accessibility]

**Landmarks and headings.** One `main`, one H1 naming the metric. The trend, the
table, related metrics and the method note are H2s.

**Focus on entry.** Focus lands on the main content at the heading naming the
metric. Changing the metric or the window updates the caption and announces the
new summary politely. It does not move focus, because a reader who has just
changed a control has not asked to be relocated.

**The text summary is always present.** Direction, magnitude, unit, window and the
number of readings, available without opening a disclosure. A reader who cannot
perceive the chart loses speed and nothing else.

**The data table is a real table** with header cells and a caption, reachable by
keyboard, and it survives being printed. A reviewer reading on paper gets numbers
rather than an empty box where a canvas was.

**Series are distinguishable without colour.** One series per chart by default;
where there are two, they are directly labelled and differ in shape.
[Colour independence](../accessibility/colour-independence.mdx) sets it out.

**No motion carries meaning.** There is no draw-on animation whose completion is
the signal that the data is complete. Under `prefers-reduced-motion` the chart is
present, finished, immediately. See
[Reduced motion](../accessibility/reduced-motion.mdx).

**Contrast.** The series against the ground, the points against the series, and the
reference band against both, measured in both themes.
[Contrast conformance](../accessibility/contrast-conformance.mdx) sets the floor.

**Text at 200%.** The caption and the summary stay legible and unclipped; the chart
may shrink or be replaced by the table; the sentence may never be truncated.
[Text resizing and zoom](../accessibility/text-resizing-and-zoom.mdx) covers it.

**Touch and pointer are not the only route to a value.** If reading an individual
point requires hovering or dragging on the chart, the same value is in the table
without gesture. See
[Target size and motor accessibility](../accessibility/target-size-and-motor.mdx).

## Status [#status]

<StubNotice
  name="trends-screen"
  issue="prashantonomy/opsinjs#0"
  questions="[
  &#x22;Where does the per-metric minimum number of readings live, so that a reviewer can find it and a component cannot invent it?&#x22;,
  &#x22;What does the screen show when the selected window contains no readings at all: an empty chart, or no chart?&#x22;,
  &#x22;May two metrics ever share an axis, and if so what words are required alongside to prevent a causal reading?&#x22;,
  &#x22;How is an annotated event (a medication change, an illness) represented, given that no component for it exists?&#x22;,
]"
/>
