Activity heatmap
FreeA year of daily activity as a grid, with selection, and a footer that opens a ranked breakdown of where the activity went over the grid.
pnpm dlx shadcn@latest add https://caliperui.site/r/activity-heatmap.json- caliper/uiTypeScript412 · 53%
- caliper/siteNext.js188 · 24%
- caliper/registry96 · 12%
- caliper/tokens61 · 8%
- notes23 · 3%
| Date | Value |
|---|---|
| 2026-01-01 | 0 |
| 2026-01-02 | 4 |
| 2026-01-03 | 8 |
| 2026-01-04 | 3 |
| 2026-01-05 | 7 |
| 2026-01-06 | 0 |
| 2026-01-07 | 0 |
| 2026-01-08 | 0 |
| 2026-01-09 | 0 |
| 2026-01-10 | 0 |
| 2026-01-11 | 0 |
| 2026-01-12 | 0 |
| 2026-01-13 | 3 |
| 2026-01-14 | 7 |
| 2026-01-15 | 2 |
| 2026-01-16 | 6 |
| 2026-01-17 | 0 |
| 2026-01-18 | 0 |
| 2026-01-19 | 0 |
| 2026-01-20 | 0 |
| 2026-01-21 | 0 |
| 2026-01-22 | 0 |
| 2026-01-23 | 0 |
| 2026-01-24 | 2 |
| 2026-01-25 | 6 |
| 2026-01-26 | 1 |
| 2026-01-27 | 5 |
| 2026-01-28 | 0 |
| 2026-01-29 | 0 |
| 2026-01-30 | 0 |
| 2026-01-31 | 0 |
| 2026-02-01 | 0 |
| 2026-02-02 | 0 |
| 2026-02-03 | 0 |
| 2026-02-04 | 1 |
| 2026-02-05 | 5 |
| 2026-02-06 | 0 |
| 2026-02-07 | 4 |
| 2026-02-08 | 0 |
| 2026-02-09 | 0 |
| 2026-02-10 | 0 |
| 2026-02-11 | 0 |
| 2026-02-12 | 0 |
| 2026-02-13 | 0 |
| 2026-02-14 | 0 |
| 2026-02-15 | 0 |
| 2026-02-16 | 4 |
| 2026-02-17 | 8 |
| 2026-02-18 | 3 |
| 2026-02-19 | 0 |
| 2026-02-20 | 0 |
| 2026-02-21 | 0 |
| 2026-02-22 | 0 |
| 2026-02-23 | 0 |
| 2026-02-24 | 0 |
| 2026-02-25 | 0 |
| 2026-02-26 | 8 |
| 2026-02-27 | 3 |
| 2026-02-28 | 7 |
| 2026-03-01 | 2 |
| 2026-03-02 | 0 |
| 2026-03-03 | 0 |
| 2026-03-04 | 0 |
| 2026-03-05 | 0 |
| 2026-03-06 | 0 |
| 2026-03-07 | 0 |
| 2026-03-08 | 0 |
| 2026-03-09 | 7 |
| 2026-03-10 | 2 |
| 2026-03-11 | 6 |
| 2026-03-12 | 1 |
| 2026-03-13 | 0 |
| 2026-03-14 | 0 |
| 2026-03-15 | 0 |
| 2026-03-16 | 0 |
| 2026-03-17 | 0 |
| 2026-03-18 | 0 |
| 2026-03-19 | 0 |
| 2026-03-20 | 6 |
| 2026-03-21 | 1 |
| 2026-03-22 | 5 |
| 2026-03-23 | 0 |
| 2026-03-24 | 0 |
| 2026-03-25 | 0 |
| 2026-03-26 | 0 |
| 2026-03-27 | 0 |
| 2026-03-28 | 0 |
| 2026-03-29 | 0 |
| 2026-03-30 | 0 |
| 2026-03-31 | 5 |
| 2026-04-01 | 0 |
| 2026-04-02 | 4 |
| 2026-04-03 | 8 |
| 2026-04-04 | 0 |
| 2026-04-05 | 0 |
| 2026-04-06 | 0 |
| 2026-04-07 | 0 |
| 2026-04-08 | 0 |
| 2026-04-09 | 0 |
| 2026-04-10 | 0 |
| 2026-04-11 | 4 |
| 2026-04-12 | 8 |
| 2026-04-13 | 3 |
| 2026-04-14 | 7 |
| 2026-04-15 | 0 |
| 2026-04-16 | 0 |
| 2026-04-17 | 0 |
| 2026-04-18 | 0 |
| 2026-04-19 | 0 |
| 2026-04-20 | 0 |
| 2026-04-21 | 0 |
| 2026-04-22 | 3 |
| 2026-04-23 | 7 |
| 2026-04-24 | 2 |
| 2026-04-25 | 6 |
| 2026-04-26 | 0 |
| 2026-04-27 | 0 |
| 2026-04-28 | 0 |
| 2026-04-29 | 0 |
| 2026-04-30 | 0 |
| 2026-05-01 | 0 |
| 2026-05-02 | 0 |
| 2026-05-03 | 2 |
| 2026-05-04 | 6 |
| 2026-05-05 | 1 |
| 2026-05-06 | 5 |
| 2026-05-07 | 0 |
| 2026-05-08 | 0 |
| 2026-05-09 | 0 |
| 2026-05-10 | 0 |
| 2026-05-11 | 0 |
| 2026-05-12 | 0 |
| 2026-05-13 | 0 |
| 2026-05-14 | 1 |
| 2026-05-15 | 5 |
| 2026-05-16 | 0 |
| 2026-05-17 | 4 |
| 2026-05-18 | 0 |
| 2026-05-19 | 0 |
| 2026-05-20 | 0 |
| 2026-05-21 | 0 |
| 2026-05-22 | 0 |
| 2026-05-23 | 0 |
| 2026-05-24 | 0 |
| 2026-05-25 | 0 |
| 2026-05-26 | 4 |
| 2026-05-27 | 8 |
| 2026-05-28 | 3 |
| 2026-05-29 | 0 |
| 2026-05-30 | 0 |
| 2026-05-31 | 0 |
| 2026-06-01 | 0 |
| 2026-06-02 | 0 |
| 2026-06-03 | 0 |
| 2026-06-04 | 0 |
| 2026-06-05 | 8 |
| 2026-06-06 | 3 |
| 2026-06-07 | 7 |
| 2026-06-08 | 2 |
| 2026-06-09 | 0 |
| 2026-06-10 | 0 |
| 2026-06-11 | 0 |
| 2026-06-12 | 0 |
| 2026-06-13 | 0 |
| 2026-06-14 | 0 |
| 2026-06-15 | 0 |
| 2026-06-16 | 7 |
| 2026-06-17 | 2 |
| 2026-06-18 | 6 |
| 2026-06-19 | 1 |
| 2026-06-20 | 0 |
| 2026-06-21 | 0 |
| 2026-06-22 | 0 |
| 2026-06-23 | 0 |
| 2026-06-24 | 0 |
| 2026-06-25 | 0 |
| 2026-06-26 | 0 |
| 2026-06-27 | 6 |
| 2026-06-28 | 1 |
| 2026-06-29 | 5 |
| 2026-06-30 | 0 |
| 2026-07-01 | 0 |
| 2026-07-02 | 0 |
| 2026-07-03 | 0 |
| 2026-07-04 | 0 |
| 2026-07-05 | 0 |
| 2026-07-06 | 0 |
| 2026-07-07 | 0 |
| 2026-07-08 | 5 |
| 2026-07-09 | 0 |
| 2026-07-10 | 4 |
| 2026-07-11 | 8 |
| 2026-07-12 | 0 |
| 2026-07-13 | 0 |
| 2026-07-14 | 0 |
| 2026-07-15 | 0 |
| 2026-07-16 | 0 |
| 2026-07-17 | 0 |
| 2026-07-18 | 0 |
| 2026-07-19 | 4 |
| 2026-07-20 | 8 |
| 2026-07-21 | 3 |
| 2026-07-22 | 7 |
| 2026-07-23 | 0 |
| 2026-07-24 | 0 |
| 2026-07-25 | 0 |
| 2026-07-26 | 0 |
| 2026-07-27 | 0 |
| 2026-07-28 | 0 |
| 2026-07-29 | 0 |
| 2026-07-30 | 3 |
| 2026-07-31 | 7 |
| 2026-08-01 | 2 |
| 2026-08-02 | 6 |
| 2026-08-03 | 0 |
| 2026-08-04 | 0 |
| 2026-08-05 | 0 |
| 2026-08-06 | 0 |
| 2026-08-07 | 0 |
| 2026-08-08 | 0 |
| 2026-08-09 | 0 |
| 2026-08-10 | 2 |
| 2026-08-11 | 6 |
| 2026-08-12 | 1 |
| 2026-08-13 | 5 |
| 2026-08-14 | 0 |
| 2026-08-15 | 0 |
| 2026-08-16 | 0 |
| 2026-08-17 | 0 |
| 2026-08-18 | 0 |
| 2026-08-19 | 0 |
| 2026-08-20 | 0 |
| 2026-08-21 | 1 |
| 2026-08-22 | 5 |
| 2026-08-23 | 0 |
| 2026-08-24 | 4 |
| 2026-08-25 | 0 |
| 2026-08-26 | 0 |
| 2026-08-27 | 0 |
| 2026-08-28 | 0 |
| 2026-08-29 | 0 |
| 2026-08-30 | 0 |
| 2026-08-31 | 0 |
| 2026-09-01 | 0 |
| 2026-09-02 | 4 |
| 2026-09-03 | 8 |
| 2026-09-04 | 3 |
| 2026-09-05 | 0 |
| 2026-09-06 | 0 |
| 2026-09-07 | 0 |
| 2026-09-08 | 0 |
| 2026-09-09 | 0 |
| 2026-09-10 | 0 |
| 2026-09-11 | 0 |
| 2026-09-12 | 8 |
| 2026-09-13 | 3 |
| 2026-09-14 | 7 |
| 2026-09-15 | 2 |
| 2026-09-16 | 0 |
| 2026-09-17 | 0 |
| 2026-09-18 | 0 |
| 2026-09-19 | 0 |
| 2026-09-20 | 0 |
| 2026-09-21 | 0 |
| 2026-09-22 | 0 |
| 2026-09-23 | 7 |
| 2026-09-24 | 2 |
| 2026-09-25 | 6 |
| 2026-09-26 | 1 |
| 2026-09-27 | 0 |
| 2026-09-28 | 0 |
| 2026-09-29 | 0 |
| 2026-09-30 | 0 |
| 2026-10-01 | 0 |
| 2026-10-02 | 0 |
| 2026-10-03 | 0 |
| 2026-10-04 | 6 |
| 2026-10-05 | 1 |
| 2026-10-06 | 5 |
| 2026-10-07 | 0 |
| 2026-10-08 | 0 |
| 2026-10-09 | 0 |
| 2026-10-10 | 0 |
| 2026-10-11 | 0 |
| 2026-10-12 | 0 |
| 2026-10-13 | 0 |
| 2026-10-14 | 0 |
| 2026-10-15 | 5 |
| 2026-10-16 | 0 |
| 2026-10-17 | 4 |
| 2026-10-18 | 8 |
| 2026-10-19 | 0 |
| 2026-10-20 | 0 |
| 2026-10-21 | 0 |
| 2026-10-22 | 0 |
| 2026-10-23 | 0 |
| 2026-10-24 | 0 |
| 2026-10-25 | 0 |
| 2026-10-26 | 4 |
| 2026-10-27 | 8 |
| 2026-10-28 | 3 |
| 2026-10-29 | 7 |
| 2026-10-30 | 0 |
| 2026-10-31 | 0 |
| 2026-11-01 | 0 |
| 2026-11-02 | 0 |
| 2026-11-03 | 0 |
| 2026-11-04 | 0 |
| 2026-11-05 | 0 |
| 2026-11-06 | 3 |
| 2026-11-07 | 7 |
| 2026-11-08 | 2 |
| 2026-11-09 | 6 |
| 2026-11-10 | 0 |
| 2026-11-11 | 0 |
| 2026-11-12 | 0 |
| 2026-11-13 | 0 |
| 2026-11-14 | 0 |
| 2026-11-15 | 0 |
| 2026-11-16 | 0 |
| 2026-11-17 | 2 |
| 2026-11-18 | 6 |
| 2026-11-19 | 1 |
| 2026-11-20 | 5 |
| 2026-11-21 | 0 |
| 2026-11-22 | 0 |
| 2026-11-23 | 0 |
| 2026-11-24 | 0 |
| 2026-11-25 | 0 |
| 2026-11-26 | 0 |
| 2026-11-27 | 0 |
| 2026-11-28 | 1 |
| 2026-11-29 | 5 |
| 2026-11-30 | 0 |
| 2026-12-01 | 4 |
| 2026-12-02 | 0 |
| 2026-12-03 | 0 |
| 2026-12-04 | 0 |
| 2026-12-05 | 0 |
| 2026-12-06 | 0 |
| 2026-12-07 | 0 |
| 2026-12-08 | 0 |
| 2026-12-09 | 0 |
| 2026-12-10 | 4 |
| 2026-12-11 | 8 |
| 2026-12-12 | 3 |
| 2026-12-13 | 0 |
| 2026-12-14 | 0 |
| 2026-12-15 | 0 |
| 2026-12-16 | 0 |
| 2026-12-17 | 0 |
| 2026-12-18 | 0 |
| 2026-12-19 | 0 |
| 2026-12-20 | 8 |
| 2026-12-21 | 3 |
| 2026-12-22 | 7 |
| 2026-12-23 | 2 |
| 2026-12-24 | 0 |
| 2026-12-25 | 0 |
| 2026-12-26 | 0 |
| 2026-12-27 | 0 |
| 2026-12-28 | 0 |
| 2026-12-29 | 0 |
| 2026-12-30 | 0 |
| 2026-12-31 | 7 |
When to use #
Use it for
- Contribution graphs and usage over time.
- Spotting weekly rhythm.
- Showing which projects or repositories the year went into.
Skip it when
- Fewer than a few weeks of data.
Decisions #
Why it is built this way, so you know what to keep when you change your copy.
Behaviour
- The breakdown opens over the grid, not below it
- The card keeps its height, so nothing under it moves when you look at the ranking, and the grid it summarises stays where your eye left it.
- Escape closes the ranking and returns to its button
- The grid is inert while the ranking covers it, so keyboard focus can never land on a hidden day.
Styling
- Shares are drawn against the largest, not the total
- The top item fills its bar and the rest compare to it, which keeps small differences readable; the percentage of the total sits beside each bar.
Usage
- Name three, count the rest
- The footer lists the top three by name and says how many more there are, so it stays one line at any width.
Installation #
pnpm dlx shadcn@latest add https://caliperui.site/r/activity-heatmap.json
Adds its 3 files to components/ui/, each with its own stylesheet, and installs their packages. No account needed. The first part also adds Caliper UI’s tokens; import them once as in Installation.
Usage #
This is the code behind the preview above. It is built from ActivityHeatmap and activityLevels.
import { ActivityHeatmap } from "@/components/ui/activity-heatmap" export function YearActivity() { const start = Date.UTC(2026, 0, 1); const data = Array.from({ length: 365 }, (_, index) => ({ date: new Date(start + index * 86400000).toISOString().slice(0, 10), value: (index * 7919) % 11 > 6 ? (index * 31) % 9 : 0 })); return ( <div className="w-full max-w-3xl"> <ActivityHeatmap label="Contributions in 2026" data={data} unit="contributions" breakdownLabel="Top repositories" breakdown={[ { label: "caliper/ui", value: 412, detail: "TypeScript" }, { label: "caliper/site", value: 188, detail: "Next.js" }, { label: "caliper/registry", value: 96 }, { label: "caliper/tokens", value: 61 }, { label: "notes", value: 23 }, ]} /> </div> ); }
API reference #
ActivityHeatmap
component
activityLevels
component
No props of its own; it accepts the native props of its root element.
Accessibility #
It exposes grid, row, rowheader, gridcell, region, group and status semantics, with aria-label, aria-busy, aria-rowcount, aria-colcount, aria-hidden and aria-selected kept in step with state. Changes that matter are announced through a live region.
Motion #
Transitions use the shared duration and easing tokens. Under prefers-reduced-motion those tokens collapse to instant and travel distances go to zero, so state changes still happen without movement.