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 }wherematrix[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.
showValueandshowPercentageare 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-hueand--heatmap-saturationCSS 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
<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)
<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)
<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
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
| Prop | Type | Default | Description |
|---|---|---|---|
data* | HeatmapData | — | Data object with row/column labels and a plain number matrix. |
showValue | boolean | true | Renders the raw numeric value inside each cell. |
showPercentage | boolean | false | Renders the cell value as a percentage of the matrix maximum inside each cell. Independent of showValue. |
height | string | number | undefined | CSS height of the heatmap container. |
className | string | undefined | Additional CSS class for the container. Use to set --heatmap-hue / --heatmap-saturation. |
onRowClick | (row, event) => void | undefined | Fired when a row header label is clicked. |
onColumnClick | (column, event) => void | undefined | Fired when a column header label is clicked. |
onCellClick | (row, column, value, event) => void | undefined | Fired when a cell is clicked. Receives the row label, column label, the numeric value, and the native mouse event. |
* Required
HeatmapData
| Prop | Type | Default | Description |
|---|---|---|---|
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
showValueandshowPercentagefor dense grids; the tooltip still provides exact values on hover. - Theme the color family via
--heatmap-hue/--heatmap-saturationon the container — keep the lightness ramp untouched so intensity remains readable. - Use
onRowClick/onColumnClick/onCellClickto drill into a slice of data.
Accessibility
- Clickable row and column headers are rendered with
role="button"andtabIndexso 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.