GitHub repository

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

live · storybook Open in Storybook

Demo loads from https://dssoca-storybook.vercel.app/. Run pnpm storybook for it to render locally.

Usage

svelte
<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.

html
<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

PropTypeDefaultDescription
rowsstring[]—Required. Row labels, top→bottom.
columnsstring[]—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.
showValuesbooleantrueRender the value text inside each cell.
xLabelstring—X axis caption drawn under the column headers.
yLabelstring—Y axis caption drawn rotated beside the row headers.
cellSizenumber48Square cell size in px.
tooltipbooleantrueReveal a tooltip on hover/focus of a cell. Each value cell is keyboard-focusable.
summarystring—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.
↑↓ navigate · ↵ open · esc close

Keyboard shortcuts

No shortcuts registered

Shortcuts added through the dssoca registry will show up here.

Single-key shortcuts