Skip to content
Charts

Heatmap Chart

Calendar heatmap. Default and Motion variants.

Examples

Installation

Default is a ready-made wrapper from the registry. Motion is the composable engine at @cronus-ui/ui/charts (peer visx + motion).

bash
npx cronus-ui add heatmap-chart
tsx
import { HeatmapChart } from "@cronus-ui/ui";

Usage

Default is the calendar Heatmap primitive (`{ date, value }[]` days). Motion is a week-column grid (`HeatmapColumn[]`) with cells, axes, legend, and tooltip as children.

tsx
import {
HeatmapChart,
HeatmapCells,
HeatmapXAxis,
HeatmapYAxis,
HeatmapLegend,
HeatmapTooltip,
} from "@cronus-ui/ui/charts";
<HeatmapChart data={weeks} layout="fluid">
<HeatmapYAxis />
<HeatmapCells />
<HeatmapXAxis />
<HeatmapLegend />
<HeatmapTooltip />
</HeatmapChart>

Components

Motion API — compose these under the chart root. Default wrapper props are in Default API below.

HeatmapChart

Week columns × weekday rows. `fluid` hugs a GitHub-style grid; `fill` expands to the parent.

Skip HeatmapChartProps props table
PropTypeDefaultDescription
data*
HeatmapColumn[]—One column per week, bins inside.
layout
"fluid" | "fill""fluid"Sizing mode.
binSize
number0Fixed cell size. 0 = square cells that fit.
gap
number2Gap between cells in px.
levelColors
HeatmapLevelColors—Five colors for Less → More.
levelStyles
HeatmapLevelStyles—Per-level color + optional pattern. Wins over levelColors.
weekStartDay
0 | 1 | … | 60First row. 0 = Sunday, 1 = Monday.
status
"loading" | "ready""ready"Loading shimmer.

HeatmapCells

The cell grid. Hover dims other cells; legend hover dims other levels.

Skip HeatmapCellsProps props table
PropTypeDefaultDescription
cornerRadius
number2Cell radius.
inactiveOpacity
number0.3Opacity of non-hovered cells.
rowOpacity
number | number[]—Per-row opacity (e.g. fade weekends).
hideGhostCells
booleantrueHide out-of-range bins.

HeatmapXAxis

Month labels along the top.

Skip HeatmapXAxisProps props table
PropTypeDefaultDescription
className
string—Label class.

HeatmapYAxis

Weekday labels. Default shows Mon / Wed / Fri.

Skip HeatmapYAxisProps props table
PropTypeDefaultDescription
tickFilter
"odd" | "even" | "all""odd"Which rows to label.
labelFormat
"full" | "initial""full"Mon vs M.

HeatmapLegend

Less → More swatches or a gradient bar. Hover a level to isolate it.

Skip HeatmapLegendProps props table
PropTypeDefaultDescription
variant
"swatches" | "gradient""swatches"Legend layout.
lessLabel
string"Less"Start caption.
moreLabel
string"More"End caption.

HeatmapSeparator

Vertical gaps between column groups (every N weeks, or by quarter).

Skip HeatmapSeparatorProps props table
PropTypeDefaultDescription
every
number—Gap before every Nth column.
groupBy
"every" | "quarter""every"Grouping mode.

HeatmapTooltip

Contribution tooltip with show/hide delay to avoid flicker.

Skip HeatmapTooltipProps props table
PropTypeDefaultDescription
formatLabel
(count, date) => string—Bottom line. Default: N contribution(s).
showDelay
number—Delay before first show (ms).
hideDelay
number—Grace period before hide (ms).

Level styles

levelStyles sets a color (and optional pattern) per contribution level 0–4. Patterns use --chart-scale-pattern-color.

tsx
<HeatmapChart
data={weeks}
levelStyles={[
{ color: "var(--chart-scale-01)" },
{ color: "var(--chart-scale-02)" },
{ color: "var(--chart-scale-03)" },
{ color: "var(--chart-scale-04)" },
{ color: "var(--chart-scale-05)" },
]}
>
<HeatmapCells />
</HeatmapChart>

Data format

ts
type HeatmapBin = { count: number; bin: number; date: Date };
type HeatmapColumn = { bin: number; bins: HeatmapBin[] }; // bins[0] = week start day
// Default wrapper (not Motion):
type HeatmapDay = { date: string; value: number };

Theming

Motion charts read `--chart-*` aliases that map onto Cronus semantic tokens (`--cronus-chart-1`…`--cronus-chart-5`, `--cronus-border`, `--cronus-fg`, surfaces). Override the aliases or the tokens — never palette scales (`bg-zinc-900`). Default wrappers use `ChartConfig` with `var(--cronus-chart-*)` / `var(--cronus-primary)`. Sequential bins use `--chart-scale-01`…`--chart-scale-05` (01 = lowest). Empty regions typically use `var(--muted)` or a mix of `--cronus-surface-base`.

Full token reference: Theming.

Dependencies

Default needs the recharts peer. Motion needs visx (and sometimes d3) as optional peers — install only what this chart uses.

bash
bun add recharts
bash
bun add @visx/heatmap @visx/responsive @visx/scale motion

.cronus

The same component declared in Cronus. Emitted at build time from the audit fixtures — the kernel renders it as HTML with no React.

PortedParity: MatchGeometry 1/1Pixel diff 0 pxLogic 1/1Parity scoreboard
default.cronus
app "audit-fixtures" {
  port 5176
}

style {
  preset aurora
  theme dark
}

component HeatmapChartDefault layout:inline style:heatmap-chart {
  label "Activity"
  text "1"
  text "3"
  text "5"
  text "2"
}

page "/audit/heatmap-chart/default" type:custom {
  use HeatmapChartDefault
}

Default API

Generated from the Default wrapper's exported types. Motion subcomponents are documented above.

HeatmapChartProps

Extends HeatmapProps

Skip HeatmapChartProps props table
PropTypeDefaultDescription
className
string—Additional class names merged onto the root.
children
ReactNode—Contents of the component.