SayUI
Content & display

Calendar Heatmap / Contribution Graph

A time-based matrix where each day is a cell and color intensity encodes activity or another numeric value.

Also known as contribution graph · activity heatmap · calendar heat map · GitHub contributions

Demo · not production-ready code

Prompt for AI

Pick a stack, copy a ready prompt, paste into Cursor / Claude / ChatGPT.

Your stack

Shapes the prompt you copy

React + Tailwind + shadcn/ui · EN

Stack: React + Tailwind + shadcn/ui. Use React with Tailwind CSS and shadcn/ui patterns (Radix-based primitives, cn(), class-first styling).

Task: implement "Calendar Heatmap / Contribution Graph".

Build a calendar heatmap for one year: weeks run left to right, weekdays run top to bottom, and each day cell maps a numeric value to a documented color-intensity bin. Include month and weekday labels, a low-to-high legend, and a hover/focus tooltip with exact date and value. Provide accessible labels or an equivalent textual summary, preserve zero-value days, and do not add table sorting, row selection, or pagination.

Anatomy:
- month and weekday axes: Columns represent weeks across time; rows align days of the week.
- day cells: One cell per date with a stable size and gap.
- color intensity scale: Discrete or continuous bins map numeric values to color without implying unrelated categories.
- legend: Explains low-to-high intensity and remains understandable beyond color alone.
- cell tooltip / accessible label: A hovered or focused cell reveals the date and value; assistive tech gets the same fact.

Preferred API / pattern: `calendar matrix component + semantic tooltip and legend`

Keep scope minimal: only this UI pattern, match existing project style.

Acceptance checks

  • Avoid: Implementing a contribution graph as a sortable data table.
  • Avoid: Color is the only way to read intensity
  • Avoid: Missing zero-value dates shifts cells out of chronological alignment.
  • Avoid: Every cell is a tab stop with no roving-focus or summary strategy.
  • Avoid: Month labels drift because week columns are calculated from inconsiste

In plain wordsHow people search for it

the GitHub-style contribution squaresa year of tiny day boxes where darker color means more activitythe calendar grid that shows streaks and daily intensitymonths across the top and weekdays down the side with colored cells

AnatomyOpen for part names

month and weekday axes
Columns represent weeks across time; rows align days of the week.
day cells
One cell per date with a stable size and gap.
color intensity scale
Discrete or continuous bins map numeric values to color without implying unrelated categories.
legend
Explains low-to-high intensity and remains understandable beyond color alone.
cell tooltip / accessible label
A hovered or focused cell reveals the date and value; assistive tech gets the same fact.

How to write itOpen for stack patterns

Web (HTML/CSS)CSS Grid or SVG + accessible day labels + tooltip
React + Tailwind + shadcn/uicalendar matrix component + semantic tooltip and legend
SwiftUILazyHGrid / Canvas with an accessible day summary
Ant Designcustom CSS grid/SVG + Tooltip; not Table

Notes

This is a matrix visualization, not a data table just because it has rows and columns. Preserve chronological order, include dates with zero activity, and use a legend plus text or accessible labels so color is not the only carrier of meaning. Keyboard users need a practical focus strategy rather than hundreds of noisy tab stops; provide an equivalent summary when the visual grid is too dense.

Common mistakesHumans and models trip here

  • Implementing a contribution graph as a sortable data table.
  • Color is the only way to read intensity: add legend text and accessible values.
  • Missing zero-value dates shifts cells out of chronological alignment.
  • Every cell is a tab stop with no roving-focus or summary strategy.
  • Month labels drift because week columns are calculated from inconsistent date boundaries.

More failure symptoms on AI broke it.

Related patterns

Spotted a wrong name or missing pattern?

Message on X