Components
Find patterns across two dimensions with color. Explore a matrix, wrap it into rings, or size stock cells by a separate weight.
npx mario-charts@latest add heatmapExplore color, shape, missing observations, and area weights.
Days × hours · intensity shows activity
Waiting for chart space
Hover, tap, or focus a cell to inspect. Use arrow keys to move, Home/End to jump, Enter to select, and Escape to dismiss.
Select an observation to see its original value.
import { HeatmapChart } from "@/components/charts/heatmap";
const data = [
{ day: "Mon", hour: "9am", visits: 0 },
{ day: "Mon", hour: "12pm", visits: 24 },
{ day: "Tue", hour: "9am", visits: null },
{ day: "Tue", hour: "12pm", visits: 36 },
];
export function Activity() {
return <HeatmapChart data={data} x="hour" y="day" value="visits"
showLegend height={360} ariaLabel="Visits by day and hour" />;
}Zero is a measurement. Hatched cells mean no observation: either the pair is absent or its value is null, undefined, or blank. Duplicate grid/radial pairs require aggregation before rendering. The matrix is limited to 10,000 combinations, including missing ones.
Sequential colors run from the observed minimum to maximum. Diverging colors use a neutral midpoint, zero by default, with a symmetric automatic range. Set domain when comparing multiple charts so the same value means the same color. The legend and inspection use that exact scale.
Radial columns run clockwise from the top, with the first row on the outer ring. Outer cells occupy more area, so compare their colors. Stock allocates area from weight; omitting weight gives equal allocation. Zero weights have no area, and small cells may have no visible label. All observations remain in the accessible source table.
Custom inspection receives the original data and index. Both are null for absent combinations; value and normalizedValue are null for any missing measurement. Handle these explicitly when migrating an existing tooltip. Stock defaults to percentage formatting; provide valueFormatter when displaying other units.
Typed props for layout, colors, area weights and inspection.
| Prop | Type | Default | Description |
|---|---|---|---|
dataRequired | readonly T[] | — | Original observations. Grid/radial require unique x/y pairs. Null, undefined and blank values mean missing; numeric strings are supported. Invalid values produce an actionable error. |
x / y / valueRequired | keyof T | — | Column, row/ring, and measurement keys. Categories retain first appearance. Stock ignores y and keeps each original row, including repeated labels. |
variant | 'grid' | 'radial' | 'stock' | 'grid' | Grid matrix, clockwise radial matrix, or stock treemap. Radial rows run from outer to inner rings. |
weight | keyof T | — | Stock area key: finite nonnegative values. Omit for equal allocation. Zero weights have no area and remain in the accessible source table. Gutters inset the allocated rectangles. |
colorScheme | 'blue' | 'green' | 'amber' | 'purple' | 'diverging' | 'blue' | Sequential palettes or blue/neutral/red diverging scale. Stock uses red/slate/green with a dark neutral midpoint, independent of colorScheme. |
colorFrom / colorTo | string | — | Endpoint CSS colors, including rgb, oklch and inherited CSS variables. Diverging scales retain a neutral middle. |
domain | readonly [number, number] | — | Fixed finite increasing color bounds containing every measurement. Omit for observed extent, symmetric around midpoint for diverging/stock. A constant sequential dataset uses one middle color. |
midpoint | number | 0 | Neutral value for diverging/stock. Fixed diverging bounds must extend below and above it. The legend uses this same piecewise scale. |
showLabels / showLegend | boolean | true / false | Category labels and the actual color scale. Stock labels sit directly on cells with measured font sizing and automatic black/white contrast. Values shrink to fit before being hidden; full text remains in inspection and the source table. |
cellRadius | number | 4 | Nonnegative grid/stock corner radius in pixels, bounded by cell size. Set 0 for flat corners. Radial cells keep circular edges. |
height / className | number / string | 320 | Stable positive frame height includes the legend and notices. className styles the measured wrapper. |
loading / error | boolean / string | null | false / null | Retain observations while loading to preserve geometry. Initial loading uses a variant-specific neutral placeholder. Empty and error states preserve frame size. |
animation | boolean | true | Cells grow at fixed positions on entrance; their final colors stay constant. Focus finishes the entrance immediately. Reduced motion is respected. |
valueFormatter / weightFormatter | (value: number) => string | — | Format inspection, legend and accessible values. Stock defaults to signed percentages; use valueFormatter for other units. Weight defaults to formatValue. |
ariaLabel / description | string | 'Heatmap chart' | Accessible chart name and additional context. One tab stop with arrow navigation, Home/End, Escape and optional Enter/Space activation. |
onClick | (item: T, colLabel: string, rowLabel: string) => void | — | Mouse, touch or keyboard activation with the original row. Missing matrix combinations have no callback. Stock passes an empty rowLabel. |
tooltipRenderer | TooltipRenderer<HeatmapChartTooltipData<T>> | — | Receives data/index (null for absent combinations), value/normalizedValue (null for missing values), labels, formattedValue, color and stock weightValue. |