Calendar Heatmap

Daily values laid out as a year calendar of weeks and weekdays, colored by intensity.

npm install @plocks/charts

Basics

Pass data keyed by YYYY-MM-DD and a date range. Columns are weeks, rows are weekdays, and days without a value are drawn empty.

Loading demo…

import { CalendarHeatmapChart } from '@plocks/charts'; import { CONTRIBUTIONS, END, START } from './data'; export function Demo() { return <CalendarHeatmapChart title="Contributions" data={CONTRIBUTIONS} startDate={START} endDate={END} />; }

Month labels

Month names sit above the calendar by default. monthLabelsPosition="bottom" moves them below, and monthLabels renames them.

Loading demo…

import { CalendarHeatmapChart } from '@plocks/charts'; import { CONTRIBUTIONS, END, START } from './data'; export function Demo() { return <CalendarHeatmapChart data={CONTRIBUTIONS} startDate={START} endDate={END} monthLabelsPosition="bottom" />; }

Weekday labels

withWeekdayLabels names the rows. firstDayOfWeek={0} starts each week on Sunday; when rows are short, every other row is labelled.

Loading demo…

import { CalendarHeatmapChart } from '@plocks/charts'; import { CONTRIBUTIONS, END, START } from './data'; export function Demo() { return <CalendarHeatmapChart data={CONTRIBUTIONS} startDate={START} endDate={END} withWeekdayLabels firstDayOfWeek={0} />; }

Colors

colors sets the levels days are bucketed into, low to high. The default is four shades of the theme's first accent color.

Loading demo…

import { CalendarHeatmapChart } from '@plocks/charts'; import { CONTRIBUTIONS, END, START } from './data'; export function Demo() { return <CalendarHeatmapChart data={CONTRIBUTIONS} startDate={START} endDate={END} colors={['#9be9a8', '#40c463', '#30a14e', '#216e39']} />; }

Split months

splitMonths starts every month in its own column, with an empty column between months.

Loading demo…

import { CalendarHeatmapChart } from '@plocks/charts'; import { CONTRIBUTIONS, END, START } from './data'; export function Demo() { return <CalendarHeatmapChart data={CONTRIBUTIONS} startDate={START} endDate={END} splitMonths />; }

Outside dates

withOutsideDates={false} leaves the days of the first and last week that fall outside the range blank.

Loading demo…

import { CalendarHeatmapChart } from '@plocks/charts'; import { CONTRIBUTIONS } from './data'; export function Demo() { return <CalendarHeatmapChart data={CONTRIBUTIONS} startDate="2025-03-12" endDate="2025-08-20" withOutsideDates={false} />; }

Cell size

rectSize, gap and rectRadius size the day cells. In a narrower box, cells shrink to fit.

Loading demo…

import { CalendarHeatmapChart } from '@plocks/charts'; import { CONTRIBUTIONS, END } from './data'; export function Demo() { return <CalendarHeatmapChart data={CONTRIBUTIONS} startDate="2025-07-01" endDate={END} rectSize={16} gap={3} rectRadius={4} />; }

Cell props

getRectProps(date, value) returns extra SVG attributes for a day, here outlining the busiest days.

Loading demo…

import { CalendarHeatmapChart } from '@plocks/charts'; import { CONTRIBUTIONS, END, START } from './data'; export function Demo() { return <CalendarHeatmapChart data={CONTRIBUTIONS} startDate={START} endDate={END} getRectProps={(date, value) => (value !== null && value >= 12 ? { stroke: '#e34948', strokeWidth: 1 } : undefined)} />; }

Tooltip

tooltip.formatter receives the hovered { date, value }. The default shows the localized date and the value.

Loading demo…

import { CalendarHeatmapChart } from '@plocks/charts'; import { CONTRIBUTIONS, END, START } from './data'; export function Demo() { return <CalendarHeatmapChart data={CONTRIBUTIONS} startDate={START} endDate={END} tooltip={{ formatter: ({ date, value }) => `${value ?? 0} contributions on ${date}` }} />; }

Legend

legend.show adds the empty color and the levels below the calendar, captioned with legend.labels (Less and More by default).

Loading demo…

import { CalendarHeatmapChart } from '@plocks/charts'; import { CONTRIBUTIONS, END, START } from './data'; export function Demo() { return <CalendarHeatmapChart data={CONTRIBUTIONS} startDate={START} endDate={END} legend={{ show: true, labels: ['Fewer', 'More'] }} />; }
Scan to open this page on your phoneplocks.dev/charts/CalendarHeatmapChart

Related charts