Skip to content
microcharts
ReferenceCoreActivityGrid

ActivityGrid

"Contribution-graph intensity: ordered values on a grid of cells, shaded in four discrete steps over an empty track."

encodes
color intensity (discrete levels) over a grid
precision
low — steer to SparkBar when exact comparison matters
nodes
1 per cell

Each cell is one slot in the series, shaded by intensity: the contribution-graph shape, read for cadence, streaks, and seasonality. There are five levels — a faint empty track plus four intensity steps — and the four steps share the exact opacity ramp HeatCell and HeatStrip use, so "how intense" means the same thing across the library. Level 0 is the empty track, because a slot with no activity is empty rather than a bottom-of-scale value. The steps are discrete bins, never a continuous gradient: a continuous ramp implies precision a handful of pixels can't deliver.

ActivityGrid
interactive · 5.42 kB · static · 2.48 kB

Install

Import & usereact/activity-grid
import { ActivityGrid } from "@microcharts/react/activity-grid";// commits — real values under “Sample data” below<ActivityGrid data={commits} title="Commits" />
Sample data
const commits = [  0, 1, 2, 1, 3, 4, 2, 0, 1, 3, 2, 4, 3, 1, 0, 2, 4, 3, 2, 1, 3, 0, 2, 3, 4, 1, 2, 0, 1, 2, 3, 4, 2,  1, 0,];
Needs package + stylesheetSet up with AI

Try it

When to use it

Use it for daily activity, streaks and cadence, and seasonality. Avoid it for exact values or for a precise comparison between two individual cells: color intensity is deliberately approximate, so pair it with a number when precision matters.

Sizing

ActivityGrid sizes from cell — the edge length of one square in viewBox units. Bump it to scale the whole grid, or drive the width from CSS to fill a container; the viewBox keeps the grid's aspect ratio.

Variants

layout="strip" collapses to a single row for inline use.

grid (default) vs strip

shape swaps the cell mark without changing the data or the levels. "round" softens the grid for product surfaces; "dot" adds space between cells in dense strips.

round vs dot

anchor aligns the grid to the real calendar: the first column pads down to the weekday of the given day (UTC), so rows read as weekdays. Weeks start on Monday by default (weekStart={1}, matching the ISO calendar); weekStart={0} switches to Sunday without touching the data. Cells fill column-major — each column is a week, top to bottom — which is what makes the grid read as a calendar rather than an arbitrary sequence.

calendar-aligned

Edge cases

empty data
all-zero (present, quiet)
single cell

Four homes

Accessibility

Intensity is a color channel, so ActivityGrid always pairs it with a numeric summary of its total and peak. That summary survives forced-colors and color-blind viewing. The interactive entry adds 2-D arrow-key navigation, announcing each cell's value as you move. Give it an anchor and every cell is a dated day, so the readout names the date rather than a position ("Mar 2: 12").

The interactive entry follows the shared interaction contract: arrow keys rove between units on both axes, Home and End jump to the ends, and a click, tap, Enter or Space selects a unit — pinning its readout so it survives blur, until you select it again or press Escape. On touch, a tap pins and a drag scrubs.

Props

PropTypeNotes
data*number[]Ordered values, one per cell.
layout"grid" | "strip"7-row calendar or single strip.
shape"square" | "round" | "dot"Cell mark: crisp square, soft corners, or padded dot.
anchorstring | DateFirst slot's calendar day (UTC) — pads the first column so weekday rows align.
weekStart0 | 1Start of week for anchor alignment (0 Sunday, 1 Monday).
cellnumberCell edge length in viewBox units.
stepsnumberIntensity steps including the zero track (default 5, GitHub-like). Same knob, same name, as CalendarStrip, CoverageStrip, GardenGrid, HeatCell, HeatStrip and SpiralYear.
domain[number, number]Explicit range for level bucketing.
titlestringAccessible name; joins the auto summary.
summarystring | falseOverride or disable the auto summary.
gapnumberGap between cells in viewBox units (default 2).
animatebooleaninteractiveOpt-in entrance motion when the chart mounts client-side — add import "@microcharts/react/motion" once. Inert on the server, on hydrated server HTML, and under prefers-reduced-motion.

Plus the shared grammar — data, domain, color, title, summary, format — and the layout props (width, height, className, style) that every chart accepts. Interactive entries also share animate and live, and — wherever a chart has more than one navigable unit — onActive, onSelect, selectedIndex and defaultSelectedIndex; and — wherever the chart shows a hover value — readout. See the shared grammar.

Related charts