Activity heatmap

A React component in Beamline's Charts & data-vis category.

A calendar of daily counts, one cell per day on a sequential ramp: weeks across, weekdays down, month and weekday labels, a legend scale, hatched days that were never recorded, and a keyboard grid that reads each day's date and value.

Use it for

  • Daily activity over weeks or months where rhythm, streaks and quiet days matter: deploys, active users, incidents, commits.

Not for

  • Comparing exact amounts between a few days (bar-chart).
  • Up/down status per day or check (tracker).
  • A trend line of one daily metric (line-chart).

Anatomy

  • title and description (figcaption)
  • table button
  • month labels (above the week columns)
  • weekday labels (Mon, Wed, Fri; pinned while the grid scrolls)
  • grid (rows = weekdays, columns = weeks)
  • day cell
  • readout (focused or hovered day, else the period summary)
  • legend scale (level swatches with their ranges, hatched “Not recorded” key)

Variants

  • 0: ramp: accent (fades into the surface at zero, both themes) · heat · cool (the system's data ramps)
  • 1: weekStartsOn: 0 (Sunday) · 1 (Monday)
  • 2: thresholds: explicit level bounds, or quarters of the busiest day

States

  • loading (skeleton)
  • empty (no days in the range)
  • unmeasured days (absent from data or null): hatched, read “Not recorded”, never zero
  • measured zero: the faint zero swatch
  • focused / hovered day (ring; readout shows its date and value)
  • selected day (ink ring that stands out on every ramp colour, aria-selected)
  • table view (every day with its value)
  • narrow widths: the grid scrolls inside its frame, opened at the latest week
  • right-to-left: weeks run from the right, ← and → swap, the scroller opens at the latest week on the left

Keyboard

  • Tab enters the grid on the selected day (or the latest one); one cell is in the tab order
  • ↑/↓ move a day, ←/→ move a week (mirrored in right-to-left)
  • Home/End go to the first/last day of the range; Page Up/Page Down move a month
  • Enter or Space selects the day (onSelectedChange); Escape clears the selection
  • Each cell's accessible name is its full date and value

Motion

Columns fade in once from the oldest week (one character stagger step every two weeks, about 300 ms for a year); instant under reduced motion. Hover arrives at once.

Props

PropTypeDefaultDescription
dataActivityDay[]—{ date: "YYYY-MM-DD", value: number | null } per day. Days in the range missing from data, or null, are unmeasured (hatched).
start / endstring—The range (ISO dates); the first and last day of data by default.
format(value: number) => string—How a day's value reads: "12 deploys".
valueLabelstring—The value column's heading in the table view. Default "Value".
thresholdsnumber[]—Lower bounds of levels 2…n (level 1 starts above zero). Default: quarters of the busiest day.
ramp"accent" | "heat" | "cool"—Colour scale. Default accent.
weekStartsOn0 | 1—First row. Default 1 (Monday).
selected / defaultSelected / onSelectedChangestring | null—The chosen day (ISO date).
localestring—Month and weekday names. Default en-US, so server and client agree.
title / hideTitle / descriptionstring / boolean / ReactNode—The figure's name (a heading unless hidden) is always its accessible name.
tableboolean—Offer “View as table”. Default true.
loadingboolean—Skeleton of the chart's shape; keeps the frame's size.
actionsReactNode—Controls beside the legend (range, offset).
classNamestring—Lands on the figure.
classNamesChartClassNames—Frame, tooltip and slice-list parts as applicable to this chart.
style / refCSSProperties / Ref<HTMLElement>—The native chart figure; layout measurement refs stay internal.

Dependencies

motion

Import

import { ActivityHeatmap } from "@/components/activity-heatmap/activity-heatmap";

Get it

Activity heatmap is part of Beamline: 190 React components and screens your coding agent (Claude Code, Codex, Cursor or any MCP client) installs into your app through Beamline's MCP server, as a ready-built package or as plain React source you can change. $49 one payment (regular $200), no subscription, a year of updates, one licence for your whole team. Get Beamline · Connect your agent

More in Charts & data-vis

  • Area chart: Amounts over time as filled areas: overlapping, stacked or as shares of 100%, five fills, two strokes, five curves, a range handle; gaps for missing…
  • Bar chart: Amounts by category as bars: columns or rows, grouped, stacked or as shares, reference lines, five looks (rounded, cells, trace, isometric, monospace), a…
  • Composed chart: Different measures on one time axis: bars, lines and areas per series, a left and a right value axis with their own formats, and reference lines.
  • Gauge: One value against a known range: a semicircle, a 270° dial or a full ring, filled or with a needle, coloured bands with their names (healthy, busy…
  • Line chart: Values over time as lines: curves, point markers, dashed series for forecasts, reference lines for limits and targets, an optional zero baseline and a…
  • Pie chart: A few shares of a whole as a pie or donut, with spaced slices, percent labels, a centre readout and a list of every slice with value and share; hovering…
  • Radar chart: A few series compared across the same five to eight dimensions as polygons on a polygon or circle grid; hover or arrow keys pick a dimension and read…
  • Radial chart: Progress of a few measures toward their targets as concentric rings, full or half circle, with a centre readout and a list of each ring's value, target…
  • Ridgeline: Distributions per group as overlapping density ridges (response time by region, order size by plan): an overlap control, median and p95 readouts per row…
  • Sankey chart: Flows between stages as bands whose width is the amount: sources to pages to outcomes, budgets to teams; hovering or focusing a node lights its flows and…
  • Slope chart: Change between two points in time per item, by value or by rank: labels on both sides that never collide, rising and falling told by the end marker (▲ ▼)…
  • Sparkline: A compact trend beside its value: point along it or focus it and use ← → to read each point; nulls are gaps. TrendLine is the bare line.
  • Streamgraph: Stacked flows over time around a centre baseline, with silhouette, wiggle, expand (shares) and zero offsets: a legend that turns layers on and off, a…
  • Treemap: Nested rectangles sized by value (spend by team, then service), squarified so tiles stay close to square: labels that fit or hide, hover and focus…
  • Waffle chart: Units of a whole as a grid of cells by category (seats used of a plan, tickets by channel): a 10×10 grid by default, hatched cells for units whose…