Build / Molecules
TrendChart
One measure over time, as columns.
Deliberately small: a shape-of-the-trend chart for a dashboard panel, not an explorable plot. It draws one series, because two measures on one set of axes is the mistake this component exists to make unavailable — a second measure gets a second chart.
Columns rather than a line, since the periods are discrete buckets: a week is a total, not a reading taken at a moment, and a line between two totals draws values that were never measured.
Every column carries its full reading as text for screen readers, and the tallest and the most recent are labelled on the cap — the two a reader actually looks for. Hovering or focusing a column shows the rest, so no value is only available by measuring a bar against nothing.
import { TrendChart } from '@meetcard/deck'Example
<TrendChart label="Profile views over time" unit="views" points={[ { label: 'W1', value: 312 }, { label: 'W2', value: 428 }, ]} />Stories
Source
const Default = () => <Card style={{ maxWidth: 420 }}>
<TrendChart
label="Profile views over time"
unit="views"
points={[
{ label: 'W1', value: 312, fullLabel: 'Week 1' },
{ label: 'W2', value: 428, fullLabel: 'Week 2' },
{ label: 'W3', value: 517, fullLabel: 'Week 3' },
{ label: 'W4', value: 427, fullLabel: 'Week 4' },
]} />
</Card>;Twelve buckets still read, because the columns thin rather than crowd.
Source
const AYear = () => <Card style={{ maxWidth: 420 }}>
<TrendChart
label="Profile views by month"
unit="views"
points={[
{ label: 'J', value: 180, fullLabel: 'January' },
{ label: 'F', value: 212, fullLabel: 'February' },
{ label: 'M', value: 264, fullLabel: 'March' },
{ label: 'A', value: 301, fullLabel: 'April' },
{ label: 'M', value: 288, fullLabel: 'May' },
{ label: 'J', value: 342, fullLabel: 'June' },
{ label: 'J', value: 398, fullLabel: 'July' },
{ label: 'A', value: 371, fullLabel: 'August' },
{ label: 'S', value: 455, fullLabel: 'September' },
{ label: 'O', value: 512, fullLabel: 'October' },
{ label: 'N', value: 486, fullLabel: 'November' },
{ label: 'D', value: 402, fullLabel: 'December' },
]} />
</Card>;When the run ends on its high point, the peak label and the latest label are the same column — one label, not two stacked on each other.
Source
const PeakIsLatest = () => <Card style={{ maxWidth: 420 }}>
<TrendChart
label="Profile views over time"
unit="views"
points={[
{ label: 'W1', value: 180 },
{ label: 'W2', value: 246 },
{ label: 'W3', value: 388 },
{ label: 'W4', value: 512 },
]} />
</Card>;A week with no traffic. Flat at the baseline, not an empty box.
Source
const NothingMeasuredYet = () => <Card style={{ maxWidth: 420 }}>
<TrendChart
label="Profile views over time"
unit="views"
points={[
{ label: 'W1', value: 0 },
{ label: 'W2', value: 0 },
{ label: 'W3', value: 0 },
{ label: 'W4', value: 0 },
]} />
</Card>;Props
| Prop | Type | Default | Description |
|---|---|---|---|
labelrequired | string | — | Names the chart for assistive tech, e.g. "Profile views over time". |
pointsrequired | TrendPoint[] | — | Points in time order, oldest first. |
formatValue | (value: number) => string | (value: number) => value.toLocaleString() | — |
unit | string | '' | What is being counted, for the spoken reading — "views", "scans". |
Also accepts everything from Omit, so id, data-* and event handlers pass straight through.