Heatmap Chart
A matrix heatmap — one hue, magnitude encoded as a quantized opacity ramp, with band scales on both axes, a value-scale legend, ring-on-hover emphasis, and a loading state.
Installation
pnpm add @blakeui/pro-reactnpm install @blakeui/pro-reactyarn add @blakeui/pro-reactbun add @blakeui/pro-reactUsage
HeatmapChart is built on visx band scales and the
motion library. It is a single component: pass data as one
{ x, y, value } cell per position. Columns and rows are derived from the distinct x and y
keys (or pinned with xDomain / yDomain), and both axes are band scales — the first chart in the
library on bands in two dimensions. Cells are square-locked: the cell size falls out of the
available width, and the chart's height follows from it.
Magnitude is encoded as opacity on a single hue — every cell is painted in color
(--chart-1 by default) and only its intensity changes, quantized into levels steps. Chart
chrome (axis labels, the legend hairline) maps to the neutral tokens.
import {HeatmapChart} from "@blakeui/pro-react";
const activity = [
{x: 0, y: "Mon", value: 4},
{x: 0, y: "Tue", value: 1},
// …
];
function App() {
return <HeatmapChart data={activity} valueLabel="Commits" />;
}Color
The ramp is deliberately single-hue. Because opacity carries the value, the chart never dims non-hovered cells the way the other charts in this library do — a dimmed high-value cell would be indistinguishable from an undimmed low-value one. Instead, hovering emphasises only the active cell, with a stroke ring and a slight scale, and leaves every other cell exactly as it was.
The lowest step sits at 0.10 rather than 0 so a zero-value cell stays visible against the card
in both light and dark. Override the whole ramp with levelOpacities, and the bucket boundaries
with thresholds.
Motion
On mount every cell fades from transparent to its encoded opacity over animationDuration on a
back-loaded curve — by default in unison, so the grid resolves as one field. Set enterStagger
above 0 to spread the fades diagonally into a dissolve instead. The encoded magnitude is a static
fillOpacity on each cell, kept deliberately separate from the animated group opacity, so the
entrance can never overwrite the data. All motion collapses to an instant render under
prefers-reduced-motion, and the chart exposes the active cell to assistive tech through a polite
live region (arrow keys move in two dimensions; Home/End jump along the row; Escape clears).
Loading state
Set status="loading" to show a stroke-only skeleton — the cell outlines with a shimmer sweeping
through them — while data resolves; flip it to "ready" and the load→ready choreography plays.
API Reference
HeatmapChart
The single chart component. Measures its container, derives band scales on both axes, quantizes the values onto the opacity ramp, and renders the cells, hover layer, legend, and loading chrome.
| Prop | Type | Default | Description |
|---|---|---|---|
data | HeatmapChartDataPoint[] | — | One cell per position: {x, y, value}. Combinations absent from the array are simply not drawn. |
xDomain | (string | number)[] | — | Explicit column order. Defaults to each distinct x in first-appearance order. |
yDomain | (string | number)[] | — | Explicit row order. Defaults to each distinct y in first-appearance order. |
xTickFormat | (key, index) => string | — | Column label. Return "" to omit one — how sparse, month-style labelling is done. Labels that would collide are culled automatically. |
yTickFormat | (key, index) => string | — | Row label. Return an empty string to omit one. |
yTickFilter | "all" | "odd" | "even" | "all" | Which row labels render — alternate them when the rows are tighter than the type. |
margin | Partial<Margin> | {top: 28, right: 16, bottom: 0, left: 40} | Plot margins — room above for column labels, a left gutter for row labels. |
height | number | — | Fixed pixel height. By default the height is derived from the square cell size. |
cellSize | number | — | Fixed cell size in px. Overrides the width-derived square. |
gap | number | 2 | Gap between cells in px — absolute, not a band-padding ratio. |
cornerRadius | number | 2 | Cell corner radius in px. |
color | string | "var(--chart-1)" | The single hue every cell is painted in; magnitude rides the opacity ramp. |
levels | number | 5 | Number of quantized steps in the ramp. |
levelOpacities | number[] | [0.1, 0.32, 0.55, 0.78, 1] | Opacity per level, low→high. The 0.10 floor keeps a zero-value cell visible against the card in both themes. |
thresholds | number[] | — | Explicit inclusive upper bounds per level (length levels - 1). Defaults to a linear quantization of [0, max(value)]. |
animationDuration | number | 1600 | Entrance duration in ms. |
enterStagger | number | 0 | Per-cell stagger as a fraction of the entrance window (0–1). 0 fades the grid in unison. |
showXAxis | boolean | true | Render the column (x) axis labels. |
showYAxis | boolean | true | Render the row (y) axis labels. |
showLegend | boolean | true | Render the value-scale legend below the plot. |
legendLessLabel | string | "Less" | Label at the low end of the legend ramp. |
legendMoreLabel | string | "More" | Label at the high end of the legend ramp. |
showTooltip | boolean | true | Show the hover tooltip layer and the ring-on-hover emphasis. |
valueLabel | string | "Value" | Name shown against the value in the tooltip. |
valuePrefix | string | — | Static text rendered before the tooltip value (e.g. "$"). |
status | "loading" | "ready" | "ready" | While loading, shows the skeleton grid. Flipping to ready plays the entrance. |
loadingLabel | string | "" | Centered caption shown while loading. Empty string hides it. |
Also supports all native div HTML attributes.
HeatmapChartDataPoint
Each entry in data describes one cell of the matrix.
| Field | Type | Description |
|---|---|---|
x | string | number | Column key. Distinct values become the columns, in first-appearance order. |
y | string | number | Row key. Distinct values become the rows, in first-appearance order. |
value | number | Magnitude driving the opacity ramp. Values at or below 0 land on level 0 — drawn as a real cell at the floor opacity, not omitted. |
Gauge Chart
A segmented notch gauge — a single value lit across a 270° arc of tapered notches, with a spring-wave entrance, a rolled center stat, and a loading state.
Line Chart
A composable line chart with multi-series strokes, an animated entrance reveal, an interpolated hover tooltip, and a loading state.