Heatmap Chart

HeatmapChart renders a 2D grid where each cell is colored by its value relative to the matrix maximum. It is pure CSS Grid (no SVG) so it scales naturally with the container.

  • Data is { rows, columns, matrix } where matrix[r][c] is the value at that row and column. Values should be non-negative.
  • Cell intensity is normalized to the matrix maximum — the highest value gets the darkest cell.
  • showValue and showPercentage are independent: enable both for full readouts, neither for a clean visualization with values on hover.
  • Click handlers (onCellClick, onRowClick, onColumnClick) all expose the native mouse event.
  • Theme the color family by overriding the --heatmap-hue and --heatmap-saturation CSS custom properties on the container.

Import

import { HeatmapChart } from "h2o-library/charts";

Usage

Value + Percentage

Show both the raw value and its percentage of the matrix maximum inside each cell — best for compact dashboards where the exact figures matter.

Value + percentage

Mon
Tue
Wed
Thu
Fri
Service A
10
25%
25
63%
15
38%
30
75%
20
50%
Service B
5
13%
40
100%
12
30%
22
55%
18
45%
Service C
35
88%
8
20%
28
70%
13
33%
24
60%
Service D
18
45%
20
50%
33
83%
9
23%
14
35%
<HeatmapChart data={data} showValue showPercentage />;

Value Only (default)

Just the raw value inside each cell. The percentage is still available in the hover tooltip.

Value only (default)

Mon
Tue
Wed
Thu
Fri
Service A
10
25
15
30
20
Service B
5
40
12
22
18
Service C
35
8
28
13
24
Service D
18
20
33
9
14
<HeatmapChart data={data} showValue />;

Dense UI Activity (no values)

Disable both showValue and showPercentage for a dense activity grid. The hover tooltip provides the exact value when needed.

GitHub-style activity (no values)

W 1
W 2
W 3
W 4
W 5
W 6
W 7
W 8
W 9
W 10
W 11
W 12
W 13
W 14
W 15
W 16
W 17
W 18
Mon
Tue
Wed
Thu
Fri
Sat
Sun
<HeatmapChart data={data} showValue={false} showPercentage={false} />;

Click Events

<HeatmapChart
  data={data}
  onCellClick={(row, column, value, e) => {
    e.stopPropagation();
    console.log(row, column, value);
  }}
  onRowClick={(row, e) => {
    e.stopPropagation();
    console.log("row:", row);
  }}
/>;

Theming

Override --heatmap-hue and --heatmap-saturation on the container to change the color family. The lightness ramp (which encodes intensity) stays the same.

.my-heatmap {
  --heatmap-hue: 150; /* green */
  --heatmap-saturation: 70%;
}
<HeatmapChart data={data} className="my-heatmap" />;

Playground

Loading playground…

Keyboard

Row headers (onRowClick), column headers (onColumnClick), and cells (onCellClick) become focusable when their handler is provided. Use Tab to move between them and Enter or Space to activate.

Props

HeatmapChart

PropTypeDefaultDescription
data*HeatmapDataData object with row/column labels and a plain number matrix.
showValuebooleantrueRenders the raw numeric value inside each cell.
showPercentagebooleanfalseRenders the cell value as a percentage of the matrix maximum inside each cell. Independent of showValue.
heightstring | numberundefinedCSS height of the heatmap container.
classNamestringundefinedAdditional CSS class for the container. Use to set --heatmap-hue / --heatmap-saturation.
onRowClick(row, event) => voidundefinedFired when a row header label is clicked.
onColumnClick(column, event) => voidundefinedFired when a column header label is clicked.
onCellClick(row, column, value, event) => voidundefinedFired when a cell is clicked. Receives the row label, column label, the numeric value, and the native mouse event.

* Required

HeatmapData

PropTypeDefaultDescription
rows*string[]Row header labels (displayed on the left).
columns*string[]Column header labels (displayed at the top).
matrix*number[][]2D matrix of plain numbers. Outer array maps to rows, inner array to columns. Values should be non-negative.

* Required

Design Guidelines

  • Use heatmaps for density or activity patterns across two categorical dimensions (e.g. day-of-week × hour-of-day).
  • Cell intensity is normalized to the matrix maximum — outliers can wash out the rest of the grid. Consider clamping or normalizing data first when one cell is much larger than the others.
  • Disable showValue and showPercentage for dense grids; the tooltip still provides exact values on hover.
  • Theme the color family via --heatmap-hue / --heatmap-saturation on the container — keep the lightness ramp untouched so intensity remains readable.
  • Use onRowClick / onColumnClick / onCellClick to drill into a slice of data.

Accessibility

  • Clickable row and column headers are rendered with role="button" and tabIndex so keyboard users can navigate them.
  • When cells render neither value nor percentage, the tooltip provides the data on hover.
  • Provide a data table view for screen reader users when the chart carries critical information.