Skip to content

Data

Heatmap

Magnitude across two dimensions — a publishing calendar, an hour × weekday grid, a cohort table.

Heatmap
import { Heatmap } from '@anomalia/ui';

Notes

  • Sequential means one hue, light to dark, never a rainbow: the whole point of the form is that "darker" reads as "more" without a lookup. The ramp is achromatic here, which is the most literal reading of the encoding and keeps the grid inside a monochrome palette.
  • **Empty is not zero.** A cell with no data gets the surface and a hairline; a real zero gets the first ramp step. Painting both the same turns "we did not measure this" into "this was nothing" — the single most common heatmap lie.
  • Values are binned into six classes rather than mapped continuously. Past about seven classes adjacent bins stop being distinguishable, so more resolution would be precision the eye cannot read.
  • A scale legend is not optional. Colour on a continuous scale with no key is a puzzle, and two labelled ends plus the swatches answer it in a glance.
  • Cells stay square and the grid scrolls sideways inside its own box. A calendar stretched to fit a card reads as a bug; a calendar that widens the page is worse.

Examples

Calendar

Sequential, so one hue light→dark and never a rainbow. Empty is not zero: a cell with no data gets the surface and a hairline, a real zero gets the first ramp step — painting both alike turns "not measured" into "nothing happened".

Publishing rhythm
W20W21W22W23W24W25W26W27W28W29W30W31W32W33W34W35W36W37W38W39
Mon3 posts2 posts0 posts3 posts1 posts2 posts2 posts1 posts2 posts2 posts3 posts3 posts2 posts1 posts1 posts0 posts2 posts2 postsno datano data
Tue1 posts2 posts1 posts1 posts0 posts1 posts0 posts0 posts3 posts3 posts0 posts2 posts2 posts2 posts1 posts2 posts0 posts0 postsno datano data
Wed4 posts3 posts5 posts4 posts3 posts4 posts5 posts5 posts4 posts3 posts3 posts3 posts2 posts2 posts2 posts3 posts3 posts3 postsno datano data
Thu3 posts0 posts2 posts3 posts1 posts2 posts0 posts2 posts3 posts2 posts1 posts1 posts1 posts2 posts3 posts2 posts3 posts2 postsno datano data
Fri1 posts2 posts3 posts1 posts2 posts2 posts1 posts1 posts1 posts2 posts2 posts2 posts2 posts0 posts1 posts1 posts2 posts2 postsno datano data
Sat1 posts1 posts1 posts0 posts0 posts1 posts0 posts1 posts1 posts1 posts1 posts1 posts0 posts0 posts0 posts1 posts0 posts1 postsno datano data
Sun0 posts0 posts1 posts0 posts1 posts0 posts1 posts0 posts1 posts1 posts1 posts1 posts1 posts1 posts1 posts0 posts1 posts1 postsno datano data
0 5 posts

API

PropTypeDefaultDescription
cellsHeatCell[]`{ x, y, value }`, where `value: null` means not measured.
columns / rowsstring[]Explicit order. Omit to take first-seen order from the cells.
sizenumber14Cell edge in px. Cells stay square.
maxnumberFixed ceiling for the scale.
unitstringWhat one unit is — shown in the legend and in each cell’s title.

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