A year of daily counts as a grid of shaded squares — the GitHub-style contribution graph, drawn for whatever your app counts per day: commits, deploys, orders, sign-ins, posts, workouts, lessons, support tickets, API calls, or a habit tracker's streak. Pass data as [{ date: '2026-08-10', count: 12 }] and it renders 53 columns of 7 squares with month and weekday headers; sparse data is fine, since a day with no row is drawn as a day with nothing, and two rows for the same day are summed rather than one silently winning. Shading is by quartile of the days that had any activity, so a single 500-commit day does not flatten the rest of the year into one pale block the way scaling against the maximum does — pass thresholds to cut the levels yourself. Dates are held as integers, days since the epoch in UTC, and never as Date objects: new Date('2026-08-10').getDay() is parsed as UTC midnight and answers with the previous day anywhere west of Greenwich, which silently rotates the whole grid by one row, and it is the single most common defect in a hand-rolled contribution graph. Nothing reads the clock either — the window is anchored to the last date in your data, not to Date.now(), so the server and the browser always render the same markup. It is a real table with month columns, weekday row headers and a screen-reader name on every square ('12 commits on Monday, August 10, 2026'), so the year is readable to somebody who cannot tell the four shades apart; conveying a value by colour alone fails WCAG 1.4.1, and the colour key is hidden from assistive technology instead of being announced as five unlabelled swatches. The grid scrolls horizontally on a narrow screen and takes keyboard focus, because a scrollable region that cannot be reached by keyboard puts a year of data out of reach. Shades are one opacity ramp of your theme's primary token, so it follows light and dark without a palette of its own. No dependencies and no hooks, so it renders inside a React server component with no 'use client' of its own and ships no client JavaScript. Official shadcn/ui has nothing that draws this: calendar is a react-day-picker date picker for choosing a day (it pulls in date-fns and the button component), and chart is a Recharts wrapper — neither plots a value per calendar day.
Provided by pulld
Install directly from the provider.
Light Mode
Dark Mode
Theme
CSS
No CSS found.