caliper uidocs

Activity heatmap

Free

A 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.

Installs components/ui/activity-heatmap.tsxDepends on d3-shapeMotion shared motion tokens
pnpm dlx shadcn@latest add https://caliperui.site/r/activity-heatmap.json
Contributions in 2026
Mon
Wed
Fri
Sun
538 contributions · 119 active days
LessMore

Contributions in 2026
DateValue
2026-01-010
2026-01-024
2026-01-038
2026-01-043
2026-01-057
2026-01-060
2026-01-070
2026-01-080
2026-01-090
2026-01-100
2026-01-110
2026-01-120
2026-01-133
2026-01-147
2026-01-152
2026-01-166
2026-01-170
2026-01-180
2026-01-190
2026-01-200
2026-01-210
2026-01-220
2026-01-230
2026-01-242
2026-01-256
2026-01-261
2026-01-275
2026-01-280
2026-01-290
2026-01-300
2026-01-310
2026-02-010
2026-02-020
2026-02-030
2026-02-041
2026-02-055
2026-02-060
2026-02-074
2026-02-080
2026-02-090
2026-02-100
2026-02-110
2026-02-120
2026-02-130
2026-02-140
2026-02-150
2026-02-164
2026-02-178
2026-02-183
2026-02-190
2026-02-200
2026-02-210
2026-02-220
2026-02-230
2026-02-240
2026-02-250
2026-02-268
2026-02-273
2026-02-287
2026-03-012
2026-03-020
2026-03-030
2026-03-040
2026-03-050
2026-03-060
2026-03-070
2026-03-080
2026-03-097
2026-03-102
2026-03-116
2026-03-121
2026-03-130
2026-03-140
2026-03-150
2026-03-160
2026-03-170
2026-03-180
2026-03-190
2026-03-206
2026-03-211
2026-03-225
2026-03-230
2026-03-240
2026-03-250
2026-03-260
2026-03-270
2026-03-280
2026-03-290
2026-03-300
2026-03-315
2026-04-010
2026-04-024
2026-04-038
2026-04-040
2026-04-050
2026-04-060
2026-04-070
2026-04-080
2026-04-090
2026-04-100
2026-04-114
2026-04-128
2026-04-133
2026-04-147
2026-04-150
2026-04-160
2026-04-170
2026-04-180
2026-04-190
2026-04-200
2026-04-210
2026-04-223
2026-04-237
2026-04-242
2026-04-256
2026-04-260
2026-04-270
2026-04-280
2026-04-290
2026-04-300
2026-05-010
2026-05-020
2026-05-032
2026-05-046
2026-05-051
2026-05-065
2026-05-070
2026-05-080
2026-05-090
2026-05-100
2026-05-110
2026-05-120
2026-05-130
2026-05-141
2026-05-155
2026-05-160
2026-05-174
2026-05-180
2026-05-190
2026-05-200
2026-05-210
2026-05-220
2026-05-230
2026-05-240
2026-05-250
2026-05-264
2026-05-278
2026-05-283
2026-05-290
2026-05-300
2026-05-310
2026-06-010
2026-06-020
2026-06-030
2026-06-040
2026-06-058
2026-06-063
2026-06-077
2026-06-082
2026-06-090
2026-06-100
2026-06-110
2026-06-120
2026-06-130
2026-06-140
2026-06-150
2026-06-167
2026-06-172
2026-06-186
2026-06-191
2026-06-200
2026-06-210
2026-06-220
2026-06-230
2026-06-240
2026-06-250
2026-06-260
2026-06-276
2026-06-281
2026-06-295
2026-06-300
2026-07-010
2026-07-020
2026-07-030
2026-07-040
2026-07-050
2026-07-060
2026-07-070
2026-07-085
2026-07-090
2026-07-104
2026-07-118
2026-07-120
2026-07-130
2026-07-140
2026-07-150
2026-07-160
2026-07-170
2026-07-180
2026-07-194
2026-07-208
2026-07-213
2026-07-227
2026-07-230
2026-07-240
2026-07-250
2026-07-260
2026-07-270
2026-07-280
2026-07-290
2026-07-303
2026-07-317
2026-08-012
2026-08-026
2026-08-030
2026-08-040
2026-08-050
2026-08-060
2026-08-070
2026-08-080
2026-08-090
2026-08-102
2026-08-116
2026-08-121
2026-08-135
2026-08-140
2026-08-150
2026-08-160
2026-08-170
2026-08-180
2026-08-190
2026-08-200
2026-08-211
2026-08-225
2026-08-230
2026-08-244
2026-08-250
2026-08-260
2026-08-270
2026-08-280
2026-08-290
2026-08-300
2026-08-310
2026-09-010
2026-09-024
2026-09-038
2026-09-043
2026-09-050
2026-09-060
2026-09-070
2026-09-080
2026-09-090
2026-09-100
2026-09-110
2026-09-128
2026-09-133
2026-09-147
2026-09-152
2026-09-160
2026-09-170
2026-09-180
2026-09-190
2026-09-200
2026-09-210
2026-09-220
2026-09-237
2026-09-242
2026-09-256
2026-09-261
2026-09-270
2026-09-280
2026-09-290
2026-09-300
2026-10-010
2026-10-020
2026-10-030
2026-10-046
2026-10-051
2026-10-065
2026-10-070
2026-10-080
2026-10-090
2026-10-100
2026-10-110
2026-10-120
2026-10-130
2026-10-140
2026-10-155
2026-10-160
2026-10-174
2026-10-188
2026-10-190
2026-10-200
2026-10-210
2026-10-220
2026-10-230
2026-10-240
2026-10-250
2026-10-264
2026-10-278
2026-10-283
2026-10-297
2026-10-300
2026-10-310
2026-11-010
2026-11-020
2026-11-030
2026-11-040
2026-11-050
2026-11-063
2026-11-077
2026-11-082
2026-11-096
2026-11-100
2026-11-110
2026-11-120
2026-11-130
2026-11-140
2026-11-150
2026-11-160
2026-11-172
2026-11-186
2026-11-191
2026-11-205
2026-11-210
2026-11-220
2026-11-230
2026-11-240
2026-11-250
2026-11-260
2026-11-270
2026-11-281
2026-11-295
2026-11-300
2026-12-014
2026-12-020
2026-12-030
2026-12-040
2026-12-050
2026-12-060
2026-12-070
2026-12-080
2026-12-090
2026-12-104
2026-12-118
2026-12-123
2026-12-130
2026-12-140
2026-12-150
2026-12-160
2026-12-170
2026-12-180
2026-12-190
2026-12-208
2026-12-213
2026-12-227
2026-12-232
2026-12-240
2026-12-250
2026-12-260
2026-12-270
2026-12-280
2026-12-290
2026-12-300
2026-12-317

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 #

terminal
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.

example.tsx
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
PropTypeDefaultDescription
label *string—
data *readonly ActivityDay[]—
breakdownreadonly ActivityShare[]—Where the activity went, largest first or not; the footer names the top three and opens the full ranking over the grid.
breakdownLabelstring"Where it went"
weekStart0 | 110 is Sunday, 1 is Monday.
unitstring""
formatValue((value: number) => string)numberText
selectedstring | null—Controlled selected date (YYYY-MM-DD); omit for uncontrolled.
onSelect((date: string | null, value: number) => void)—
loadingboolean—
errorstring—
classNamestring—

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.

KeyBehaviour
→Moves to the next item or value.
←Moves to the previous item or value.
↓Moves to the next item or value.
↑Moves to the previous item or value.
PageDownMoves by a larger step, or to the next page.
PageUpMoves by a larger step, or to the previous page.
HomeJumps to the first item or the minimum.
EndJumps to the last item or the maximum.
EnterActivates the focused control.
SpaceActivates the focused control.
EscapeCloses or cancels, then returns focus to where it came from.

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.