Heatmap Chart

Documentation Index

Fetch the complete documentation index at: /llms.txt. Use this file to discover all available pages before exploring further.

A GitHub-style calendar heatmap — one cell per day, colored by intensity — powered by Apache ECharts

Basic Chart

Installation

npx shadcn@latest add @evilcharts/echarts-heatmap-chart

Usage

The heatmap is the GitHub contribution graph shape: a calendar year laid out as week columns, one square per day, with color intensity standing in for the value. <EChartsHeatmapChart> is the container, and every part hangs off it as a compound member — <EChartsHeatmapChart.Cell>, <EChartsHeatmapChart.MonthLabel>, <EChartsHeatmapChart.DayLabel>, <EChartsHeatmapChart.Tooltip>, and <EChartsHeatmapChart.Legend> — so a single import gives you the whole chart. The cells are intrinsic to the data, so <Cell> always renders and just configures the grid; the labels, tooltip, and legend follow presence semantics — omit one and it does not render.

import { EChartsHeatmapChart, type ChartConfig, type HeatmapDatum } from "@/components/evilcharts/charts/echarts-heatmap-chart";
// One entry per day that has a value. Days you leave out render as empty cells.
const data: HeatmapDatum[] = [
  { date: "2025-01-06", value: 3 },
  { date: "2025-01-07", value: 11 },
  { date: "2025-01-09", value: 1 },
  // ...
];
 
// The color array IS the intensity ramp — lightest first, strongest last.
const chartConfig = {
  contributions: {
    label: "Contributions",
    colors: {
      light: ["#9be9a8", "#40c463", "#30a14e", "#216e39"],
      dark: ["#0e4429", "#006d32", "#26a641", "#39d353"],
    },
  },
} satisfies ChartConfig;
 
<EChartsHeatmapChart className="h-48" data={data} config={chartConfig}>
  <EChartsHeatmapChart.Cell dataKey="contributions" />
  <EChartsHeatmapChart.MonthLabel />
  <EChartsHeatmapChart.DayLabel />
  <EChartsHeatmapChart.Tooltip />
  <EChartsHeatmapChart.Legend />
</EChartsHeatmapChart>

Under the hood these compound children are declarative configuration slots rather than visual React DOM nodes. The root reads their props and compiles an ECharts option — a calendar coordinate system for the date math, and a custom series for the cells so they can carry a gap, rounded corners, and a per-day color — which ECharts paints with Canvas by default or SVG when renderer="svg".

config is the same contract as every EvilCharts chart — a key maps to a label and a per-theme colors array. See Chart Config for the full shape. Here the array does double duty: its length is the number of intensity levels, and each entry is that level's color. Colors resolve from CSS variables at runtime, so dark mode just works.

SVG Renderer

Pass renderer="svg" to the chart root to opt into ECharts' SVG renderer. Omit it to use the default Canvas renderer.

renderer="svg"

Interactive Selection

Set isClickable on <Cell> to make days selectable. The selected day keeps full strength and wears a ring while the rest soften. Handle selection events with the root's onSelectionChange callback:

isClickable
<EChartsHeatmapChart
  data={data}
  config={chartConfig}
  onSelectionChange={(selection) => {
    if (selection) {
      console.log("Selected:", selection.date, "Value:", selection.value);
    } else {
      console.log("Deselected");
    }
  }}
>
  <EChartsHeatmapChart.Cell dataKey="contributions" isClickable />
  <EChartsHeatmapChart.Tooltip />
</EChartsHeatmapChart>

Loading State

isLoading='true'

Examples

Examples of the heatmap in different configurations. Customize the root range, weekStart, and scale, the <Cell> radius and gap, and more.

Calendar Year

range={2025} scale='linear'

Monday Start

weekStart='monday'

Rounded Cells

radius={6} gap={5}

Explicit Thresholds

thresholds={[3, 10]}

API Reference

A root container plus a small set of composible parts. Render the root, then compose the parts you need as children. Each part is declarative config the root compiles into the ECharts option.

EChartsHeatmapChart

The root container. It owns the date window, the value → level mapping, shared selection state, the loading skeleton, and the intro sweep. Everything visual is composed as children and compiled into the ECharts option.

PropTypeDefaultDescription
data*HeatmapDatum[]–

One entry per day that has a value. HeatmapDatum is { date: string; value: number }, where date is an ISO calendar date (YYYY-MM-DD). Days absent from the array render as empty cells; duplicate dates are summed.

config*ChartConfig–

Defines the series. The key named by <Cell dataKey> supplies a label and a per-theme colors array that becomes the intensity ramp — lightest first, strongest last. Same contract as every EvilCharts chart — see Chart Config.

children*ReactNode–

The composed parts — <Cell />, <MonthLabel />, <DayLabel />, <Tooltip />, and <Legend />.

classNamestring–

Additional CSS classes for the chart container.

renderercanvas|svg"canvas"

Rendering engine used by ECharts. Use "svg" for an SVG-backed chart surface; omit the prop to keep the Canvas default.

rangenumber | string | [string, string]–

The calendar window. A year (2025) shows January through December, a month string ("2025-03") shows that month, and an [start, end] pair of ISO dates shows that inclusive span. Omit it for the trailing year ending on the latest date in data.

weekStartsunday|monday"sunday"

Which day sits on the top row of each week column.

cellSizenumber–

A fixed cell size in pixels. Omit it to fit square cells to the container's width (capped by its height) and re-fit on resize.

scalequantile|linear"quantile"

How values map onto the ramp when no thresholds are given. "quantile" shares the non-zero days evenly across the levels, like GitHub, so a few huge days don't wash out the rest; "linear" divides the min→max span evenly.

thresholdsnumber[]–

Explicit ascending level boundaries. Values below the first threshold are level one; each threshold a value reaches moves it up a level. n thresholds make n + 1 levels, spread across however many colors the config provides.

defaultSelectedDatestring | nullnull

The ISO date selected on first render.

onSelectionChange(selection: { date: string; value: number } | null) => void–

Called when a day is selected or deselected. Receives the day's date and value, or null on deselect. Fires on click while <Cell /> has isClickable set.

isLoadingbooleanfalse

Shows the animated loading skeleton.

animationbooleantrue

Master switch for the intro sweep. Pass false to render the chart instantly.

animationTypenone|default"default"

"default" pops the cells in column by column, left to right, on first render; "none" disables it. The OS reduce-motion preference falls back to "none" automatically.

chartOptionsRecord<string, unknown>–

Escape hatch merged over the built ECharts option object. See the ECharts calendar option documentation.

Cell

Configures the day cells. Always renders — it names the config key to color the grid with and shapes each cell.

PropTypeDefaultDescription
dataKey*string–

The config key whose colors array forms the intensity ramp and whose label names the value in the tooltip.

radiusnumber2

The corner radius of each cell in pixels. Set to 0 for square cells.

gapnumber3

The space between neighboring cells in pixels.

isClickablebooleanfalse

Lets days be clicked to select/deselect them. The selected day keeps full strength and wears a ring while the rest soften.

MonthLabel

Shows month names above the grid, each over the column where the month begins. Its presence enables it; omit it and none show.

PropTypeDefaultDescription
labelsstring[]["Jan", …, "Dec"]

Twelve month names, January first.

DayLabel

Shows weekday names beside the grid. Its presence enables it; omit it and none show.

PropTypeDefaultDescription
labelsstring[]["", "Mon", "", "Wed", "", "Fri", ""]

Seven day names, Sunday first, regardless of weekStart. An empty string leaves that row unlabeled — the default labels every other row, like GitHub.

Tooltip

The hover tooltip. Its presence enables it; omit it and none shows. Hovering a day shows the formatted date as the title and the series label with that day's value beneath it. Hidden automatically while loading.

PropTypeDefaultDescription
variantdefault|frosted-glass"default"

Controls the visual style of the tooltip surface.

roundnesssm|md|lg|xl"lg"

Controls the border-radius of the tooltip.

positionfixed|variable"variable"

Controls how the tooltip is anchored. "variable" follows the pointer (ECharts' default); "fixed" pins the tooltip near the top and only tracks the pointer's X.

dateFormatter(date: string) => string–

Formats the hovered day's ISO date for the tooltip title. Defaults to "Mar 3, 2026" style English.

valueFormatter(value: number) => string(value) => value.toLocaleString()

Formats the hovered day's value.

Legend

The "Less → More" ramp rendered under the grid, one swatch per level plus the empty cell. Its presence enables it; omit it and none shows. Hidden while loading.

PropTypeDefaultDescription
alignleft|right"right"

Which side of the chart the ramp sits on.

lessLabelstring"Less"

Text before the ramp.

moreLabelstring"More"

Text after the ramp.