Heatmap Calendar

1,198 commits in the last 53 weeks
About this component

Heatmap Calendar

A contribution calendar in the GitHub style: one square per day in week columns, shaded from a single color in five steps whose thresholds follow the data's quantiles or your own. Month and weekday labels, a Less to More legend and an optional total frame the grid; a rolling range of weeks or a whole calendar year, weeks starting on Sunday or Monday, and names and numbers in any locale. Hovering or focusing a day lifts it with a tooltip of its date and value; the grid is one tab stop with arrow keys by day and week, and days can be made selectable. All date maths is in UTC, so a day never shifts with the reader's time zone, and wide ranges scroll sideways, opening on the latest week.

Usage

The import and the props worth knowing about, in one place.

import { HeatmapCalendar } from "@/components/beste/component/heatmap-calendar";

// A rolling year that ends on the latest date in the data
<HeatmapCalendar data={[{ date: "2026-09-27", value: 4 }, { date: "2026-09-26", value: 1 }]} />

<HeatmapCalendar
  data={activity}
  year={2026}                     // a whole calendar year instead of a rolling range
  weekStartsOn={1}                // Monday
  locale="de-DE"
  color="#16a34a"                 // any CSS color; lighter steps are mixed from it
  levels={5}                      // shades including the empty one
  thresholds={[1, 3, 6, 10]}      // lowest value of each non-empty level
  unit={["session", "sessions"]}
  showTotal
  onSelectedChange={(date, day) => console.log(date, day.value)}
/>

Keyboard and gestures

Every one of these is in the component already. They are listed because a props table cannot mention a gesture, so nothing else on this page can tell you they exist.

Up / DownThe day before or after.
Left / RightThe same weekday a week earlier or later.
Page Up / Page DownFour weeks back or forward.
Home / EndThe first or last day of the week; with Cmd or Ctrl, of the whole range.

Props

Read from the component's own type, so this cannot drift from what it accepts.

PropTypeDefaultDescription
dataHeatmapDay[]—
endDatestring—Last day shown. Defaults to the latest date in `data`, or today once mounted.
weeksnumber—Weeks shown, counting back from `endDate`. Ignored when `year` is set.
yearnumber—Show one calendar year, January to December, instead of a rolling range.
weekStartsOn0 | 1—0 starts weeks on Sunday, 1 on Monday.
localestring—Locale for month and weekday names and for numbers.
colorstring—The scale's strongest color, any CSS color. Lighter levels are mixed from it.
levelsnumber—Number of shades including the empty one, 3 to 9.
thresholdsnumber[]—Lowest value of each non-empty level, ascending. Computed from quantiles when left out.
unit[string, string]—Singular and plural word for the value, used in labels and the total.
formatValue(value: number, date: string) => string—Custom text for a day's value in the tooltip and its label.
labelstring—Accessible name of the grid.
showMonthLabelsboolean—
showWeekdayLabelsboolean—
showLegendboolean—
showTotalboolean—Total of the range, shown beside the legend.
selectedstring | null—Selected day, controlled.
defaultSelectedstring | null—
onSelectedChange(date: string, day: HeatmapDay) => void—Fires when a day is picked with a click, Enter or Space. Days become selectable when this or `selected` is set.
size"sm" | "default" | "lg"—
tone"muted" | "outline" | "ghost"—
classNamestring—

More Heatmap components

View all Heatmap
Weekday12a6a12p6p
Mon
Tue
Wed
Thu
Fri
Sat
Sun
Busiest: Saturday, 9 PM (61 sessions)