Skip to content
microcharts
ReferenceCoreHeatCell

HeatCell

React heat cell chart — one intensity cell for a table cell or matrix slot. Tiny accessible SVG microchart; RSC-safe static or /interactive.

encodes
discrete color step
precision
low — use MiniBar/DotPlot for precise comparison
nodes
≤ 2 (cell + optional value label)

HeatCell answers "how intense is this one value against a known scale?". It is the single-cell building block for grids you lay out yourself — a matrix of tenants × hours, a custom calendar, a density chip in a sentence. Color is quantized into discrete steps: continuous opacity would fake precision a 12-px cell can't deliver.

HeatCell
interactive · 3.36 kB · static · 2.03 kB

Install

Import & usereact/heat-cell
import { HeatCell } from "@microcharts/react/heat-cell";<HeatCell value={42} domain={[0, 100]} title="Load" />
Needs package + stylesheetSet up with AI

Try it

When to use it

  • Good for — table-cell matrices, custom grids, intensity chips beside labels.
  • Avoid for — precise comparison (MiniBar, DotPlot) or time series (HeatStrip, ActivityGrid).

The shared-domain rule

A lone cell has no data to auto-scale from, so domain defaults to [0, 1] — pass your grid's real scale. Every cell in one grid must share one domain: per-cell auto-scaling would make the brightest hour of a quiet tenant look like the brightest hour of a loud one.

// one domain, computed once, shared by every cell
const domain: [number, number] = [0, Math.max(...allValues)];
rows.map((r) => r.hours.map((v) => <HeatCell value={v} domain={domain} />));

Sizing

Variants

shapes
value chip

Edge cases

non-finite value — a designed empty track
value at the domain floor and ceiling — clamped, not rescaled

Four homes

Why this default

Five steps is the most a reader reliably distinguishes at cell size — the same ramp ActivityGrid uses, so intensity means one thing across the library. Values outside the domain clamp to the end steps (documented, never silently rescaled), and a zero-width domain renders the single mid step with a dev warning.

Accessibility

The accessible name carries the value and its calibration — the shape cells above read "70 — level 4 of 5." — so the color scale is never the only channel. Non-finite input renders a designed empty track and says "No data." The interactive entry reveals the same reading on hover/focus, with ActivityGrid announcement parity.

This chart is a single unit, so there is nothing to rove between: a click, tap, Enter or Space selects it and fires onSelect, and no selection stays pinned. That is the scalar half of the shared interaction contract. Hover or focus also reveals the reading itself in a floating chip, for the sizes and label modes where the mark does not print it; readout={false} drops the chip and keeps everything else.

Props

PropTypeNotes
value*numberThe value to calibrate.
domain[number, number]Calibration scale — defaults to [0, 1]; every cell in a grid must share one.
stepsnumberDiscrete perceptual steps (default 5, shared with ActivityGrid).
shape"square" | "round" | "dot"Shared cell vocabulary.
label"value" | "none"Centered number when the cell doubles as a chip.
animatebooleaninteractiveOpt-in entrance motion when the chart mounts client-side — add import "@microcharts/react/motion" once. Inert on the server, on hydrated server HTML, and under prefers-reduced-motion.

Plus the shared grammar — data, domain, color, title, summary, format — and the layout props (width, height, className, style) that every chart accepts. Interactive entries also share animate and live, and — wherever a chart has more than one navigable unit — onActive, onSelect, selectedIndex and defaultSelectedIndex; and — wherever the chart shows a hover value — readout. See the shared grammar.

Related charts