Skip to content

Data

Sparkline, BarChart & LineChart

Change over time and magnitude across categories, with the mark specs, the legend, the tooltip and the table view already decided.

Sparkline BarChart LineChart ChartFrame
import { Sparkline, BarChart, LineChart, ChartFrame } from '@anomalia/ui';

Notes

  • One series is ink, not a hue. Colour encodes *identity*, so a chart with nothing to tell apart has no reason to spend it — which is also what keeps a monochrome system monochrome until a stacked bar genuinely needs six colours.
  • The six categorical slots are a validated set, not a taste call: checked for the lightness band, the chroma floor, adjacent-pair separation under deuteranopia, protanopia and tritanopia, and normal-vision separation. Worst adjacent CVD ΔE 9.1 light / 8.4 dark against a target of 8. **The order is the safety mechanism** — reassigning a slot voids the guarantee.
  • Colour follows the entity, never its rank. Filtering a series out must not repaint the survivors, or a reader who learned "Instagram is blue" has been misled.
  • There is no dual-axis prop and there will not be one. Two y-scales make the alignment between them arbitrary, so the chart invents a correlation that is not in the data — the single most common way a dashboard chart lies. Two measures of different magnitude are two charts, or both indexed to 100 at t0.
  • Bars cap at 24px and never fill their band; they are rounded at the data end and square at the baseline, so a stack reads as one bar growing out of the axis. A 2px surface gap does the separating — never a stroke, which is ink that is not data.
  • A null breaks a line rather than being interpolated across. Drawing straight through missing data is a claim about data that does not exist.
  • Every multi-series chart ships a legend and a table view. That is what makes colour a redundant channel rather than the only one — and it is the condition under which a light-mode hue below 3:1 is legitimate as a *mark*.
  • Hover is a crosshair on lines and a whole-column highlight on bars, because the comparison is across series at one x, not one dot. Emphasis dims the others rather than tinting the one, so the legend keeps matching.
  • Axis ticks land on round numbers via niceDomain, and compact only abbreviates past a thousand — "0.9K" is worse than 900 in every way.

Examples

Sparkline

A sparkline answers one question — which way is this going — at the size of a word. No axes, no legend, no tooltip: the moment an exact value matters, it is the wrong chart.

Reach

+18%

184.2k

Failed jobs

+31

31

Inline

A sparkline also works at line height, next to the number it belongs to.

4.71%

Bars

Bars cap at 24px and never fill their band — the leftover is air. Rounded at the data end only, square at the baseline, so a stack reads as one bar growing out of the axis. Hover dims the others rather than tinting the one, so the legend keeps matching.

Posts published by channel

  • Instagram
  • LinkedIn
  • TikTok

Line

A crosshair rather than per-point hover: the pointer maps to the nearest column and reads every series at once, which is the comparison the chart exists for. Nulls break the line instead of being interpolated across.

Reach by channel

  • Instagram
  • LinkedIn
  • TikTok

Engagement rate

API

LineChart

PropTypeDefaultDescription
seriesSeries[]`{ id, label, values, color? }`. `id` is the identity colour follows.
labelsstring[]One per x position. Ticks thin to fit; the table keeps them all.
areabooleanfalseA 10% wash under the line. Single series only — stacked washes read as a colour nobody chose.
zerobooleantrueInclude zero in the domain. Turn it off for a rate or an index.
endLabelsbooleantrueThe final value beside each line — the selective label.

BarChart

PropTypeDefaultDescription
labels / seriesstring[] / Series[]One bar per label; several series stack.
showValuesbooleanfalseThe total on each cap, and only when the bar is wide enough for it.
maxnumberFixed ceiling. The floor is always zero.

Shared

PropTypeDefaultDescription
titlestringNames the chart for assistive tech and captions the table.
tableViewbooleantrueThe WCAG-clean twin. Turn it off only if you render your own.
format(n) => stringcompactAxis, labels and tooltip.
toolbarSnippetControls beside the title — a range picker, a series toggle.

Every component also forwards the native attributes of its root element, plus class, so anything not listed here still works.