Heatmap Grid
Cell grid filling by intensity, contribution-graph style. Install with npx remotion-ui@latest add heatmap-grid.
PrimitiveData & mediaAdvanced
$ npx remotion-ui@latest add heatmap-gridA contribution graph that fills in on a diagonal wave.
import { HeatmapGrid } from "@/remotion/primitives/heatmap-grid";
<HeatmapGrid
cells={weeks}
rowLabels={["Mon", "", "Wed", "", "Fri", "", "Sun"]}
columnStaggerInFrames={3.4}
rowStaggerInFrames={1.6}
/>cells is row-major. Ragged rows are padded with empty cells, so a partial
final week needs no placeholder values.
The wave
Cells are staggered by column × columnStaggerInFrames + row × rowStaggerInFrames. Keep the row stagger smaller than the column stagger and
the fill sweeps as a diagonal front. Staggering by flat index instead makes the
fill snake back to the left edge on every new row, which reads as a glitch.
The exit drains along the same diagonal.
Reading intensity
Intensity drives colour and a small scale step. Colour alone is hard to judge
at cell size on a dark stage; the size difference is what lets a busy column
register in peripheral vision. Empty cells stay at emptyColor and never scale
up, so a quiet week stays quiet.
maxValue pins the top of the ramp. Leave it unset and the busiest cell present
defines it. Set it explicitly when several grids need to be compared.
Staggering by column plus row makes the fill sweep as a diagonal front; a flat index stagger snakes back to the left edge on every new row and reads as a glitch. Intensity drives colour and a small scale step together, since colour alone is hard to judge at cell size on a dark stage.
Agent notes
Install first, then import the copied source component locally. AI guide →
@/remotion/primitives/heatmap-grid- Use when: frame-level motion primitives and reusable animation wrappers.
- Customize: cells, maxValue, cellSize, gap, plus copied source for timing, layout, colors, and typography.
- Rule: do not import this component from the
remotion-uinpm package; it is copied into your project.
Usage
import { HeatmapGrid } from "@/remotion/primitives/heatmap-grid";
<HeatmapGrid
cells={weeks}
rowLabels={["Mon", "", "Wed", "", "Fri", "", "Sun"]}
columnStaggerInFrames={3.4}
/>API Reference
| Prop | Type | Default | Description |
|---|---|---|---|
| cells | number[][] | required | Row-major intensities. Ragged rows are padded with empty cells. |
| maxValue | number | busiest cell | Top of the ramp. Set it explicitly to compare two grids. |
| cellSize | number | 34 | Cell edge length in px. |
| gap | number | 8 | Space between cells. |
| color | string | "#e8b86d" | Colour at full intensity. |
| emptyColor | string | rgba(250,250,250,0.07) | Colour of a zero cell. |
| rowLabels | string[] | undefined | Labels down the left gutter, one per row. |
| columnLabels | string[] | undefined | Labels along the top. Sparse arrays are fine. |
| showLegend | boolean | true | "Less → more" ramp under the grid. |
| durationInFrames | number | 14 | Length of one cell's fill. |
| columnStaggerInFrames | number | 3 | Frames added per column as the wave crosses. |
| rowStaggerInFrames | number | 1.5 | Frames added per row. Keep it below the column stagger. |
| exitAtInFrames | number | undefined | Frame the grid drains on, along the same diagonal. |
| frame | number | undefined | Frame override: pass the parent frame inside a `<Sequence>`. |