ActivityGrid
React activity grid chart — contribution-graph intensity on a calendar or matrix. Tiny accessible SVG microchart; RSC-safe static or /interactive.
ActivityGrid maps ordered values onto a grid of cells, each shaded by intensity. It's the contribution-graph shape: cadence, streaks, and seasonality, readable at a glance.
Install
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,];Try it
When to use it
- Good for — daily activity, streaks and cadence, seasonality at a glance.
- Avoid for — exact values, or precise comparison between two individual cells. Color intensity is deliberately approximate; 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.
shape swaps the cell mark — same data, same levels, different voice: "round" for friendlier product surfaces,
"dot" adds breathing room in dense strips.
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 — Monday first by default (weekStart={0} for Sunday).
Edge cases
Four homes
Why this default
Five levels (the empty track plus four intensity steps) matches the five steps HeatCell and HeatStrip default to, and
the four intensity steps share their exact opacity ramp — one calibration means "how intense" reads the same across the
library, and a reader never has to relearn a color scale per chart. Only level 0 differs: here it is a faint empty
track, because an activity slot with no activity is genuinely empty, not a bottom-of-scale value. Levels are discrete,
never a continuous gradient: a continuous ramp implies precision a handful of pixels can't actually deliver, and
discrete bins are honest about that. Monday-first weeks (weekStart={1}) match the ISO calendar most teams already
track cadence against; weekStart={0} switches to Sunday-first without touching the data. Column-major fill (each
column is a week, top-to-bottom) is what makes the grid read as a calendar instead of an arbitrary sequence of cells.
Accessibility
Intensity is a color channel, so ActivityGrid always pairs it with a numeric summary of its total and peak — the information survives forced-colors and color-blind viewing. The interactive entry adds 2-D arrow-key navigation, announcing each cell's value as you move.
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
| Prop | Type | Notes |
|---|---|---|
| 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. |
| anchor | string | Date | First slot's calendar day (UTC) — pads the first column so weekday rows align. |
| weekStart | 0 | 1 | Start of week for anchor alignment (0 Sunday, 1 Monday). |
| cell | number | Cell edge length in viewBox units. |
| domain | [number, number] | Explicit range for level bucketing. |
| title | string | Accessible name; joins the auto summary. |
| summary | string | false | Override or disable the auto summary. |
| animate | boolean | interactiveOpt-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
Bullet
React bullet chart — measured value against a target tick and qualitative bands. Tiny accessible SVG microchart; RSC-safe static or /interactive.
TrendArrow
React trend arrow chart — direction and magnitude of change as a compact arrow. Tiny accessible SVG microchart; RSC-safe static or /interactive.