Heatmap
Token-driven matrix where cell colour intensity encodes value.
A token-driven matrix/grid where each cell's colour intensity encodes its value, with row and column headers. Every cell is filled with `--ss-primary` and varies its opacity across a linear scale over the value domain, so the brightest cells are the strongest. `null` values render a blank cell that is excluded from the scale — ideal for a head-to-head win matrix where the diagonal (self) is empty. Every value cell is keyboard-focusable with an accessible tooltip, and empty input shows an em-dash placeholder.
Demo
Usage
<script>
import { Heatmap } from 'dssoca';
const players = ['Ana', 'Bruno', 'Caio', 'Duda'];
const wins = [
[null, 5, 7, 9],
[3, null, 6, 8],
[2, 4, null, 5],
[1, 2, 3, null],
];
</script>
<Heatmap
rows={players}
columns={players}
values={wins}
xLabel="Opponent"
yLabel="Player"
/>HTML
CSS only — static markup The exact markup the component renders, generated at build time. Use it with dssoca/vanilla.css — see Plain HTML & CSS.
<div class="ss-heatmap" role="group" aria-label="Heatmap, 2 rows × 3 columns.">
<div class="plot">
<svg class="canvas" viewBox="0 0 216 124" width="216" height="124" preserveAspectRatio="xMidYMid meet" role="presentation">
<text class="header col" x="96" y="20" text-anchor="middle">mon</text>
<text class="header col" x="144" y="20" text-anchor="middle">tue</text>
<text class="header col" x="192" y="20" text-anchor="middle">wed</text>
<text class="header row" x="64" y="52" dy="0.32em" text-anchor="end">api</text>
<text class="header row" x="64" y="100" dy="0.32em" text-anchor="end">db</text>
<rect class="cell" x="72" y="28" width="48" height="48" fill="var(--ss-primary)" fill-opacity="0.37142857142857144" tabindex="0" role="button" aria-label="api vs mon: 3">
</rect>
<text class="cell-text" x="96" y="52" dy="0.32em" text-anchor="middle">3</text>
<rect class="cell" x="120" y="28" width="48" height="48" fill="var(--ss-primary)" fill-opacity="0.8742857142857142" tabindex="0" role="button" aria-label="api vs tue: 7">
</rect>
<text class="cell-text" x="144" y="52" dy="0.32em" text-anchor="middle">7</text>
<rect class="cell" x="168" y="28" width="48" height="48" fill="var(--ss-primary)" fill-opacity="0.24571428571428572" tabindex="0" role="button" aria-label="api vs wed: 2">
</rect>
<text class="cell-text" x="192" y="52" dy="0.32em" text-anchor="middle">2</text>
<rect class="cell" x="72" y="76" width="48" height="48" fill="var(--ss-primary)" fill-opacity="0.6228571428571428" tabindex="0" role="button" aria-label="db vs mon: 5">
</rect>
<text class="cell-text" x="96" y="100" dy="0.32em" text-anchor="middle">5</text>
<rect class="cell" x="120" y="76" width="48" height="48" fill="var(--ss-primary)" fill-opacity="0.12" tabindex="0" role="button" aria-label="db vs tue: 1">
</rect>
<text class="cell-text" x="144" y="100" dy="0.32em" text-anchor="middle">1</text>
<rect class="cell" x="168" y="76" width="48" height="48" fill="var(--ss-primary)" fill-opacity="1" tabindex="0" role="button" aria-label="db vs wed: 8">
</rect>
<text class="cell-text" x="192" y="100" dy="0.32em" text-anchor="middle">8</text>
</svg>
</div>
</div>Rendered geometry: copy as-is. Hover tooltips are not wired by vanilla.js.
Props
| Prop | Type | Default | Description |
|---|---|---|---|
rows | string[] | — | Required. Row labels, top→bottom. |
columns | string[] | — | Required. Column labels, left→right. |
values | (number | null)[][] | — | Required. `values[r][c]`; `null` renders a blank cell excluded from the colour scale (e.g. the diagonal). |
domain | [number, number] | — | Value range mapped to colour intensity; defaults to the [min, max] of all non-null values. |
valueFormat | (v: number) => string | — | Format a cell value for its text + tooltip. |
showValues | boolean | true | Render the value text inside each cell. |
xLabel | string | — | X axis caption drawn under the column headers. |
yLabel | string | — | Y axis caption drawn rotated beside the row headers. |
cellSize | number | 48 | Square cell size in px. |
tooltip | boolean | true | Reveal a tooltip on hover/focus of a cell. Each value cell is keyboard-focusable. |
summary | string | — | Screen-reader summary + accessible name; auto-generated when absent. |
size | 'sm' | 'md' | 'lg' | — | Per-instance size override; inherits the ancestor `data-size-variant` when unset. |