contribution-graph
kibo-ui-registry/contribution-graphFreeComponent
A GitHub-style contribution graph component that displays activity levels over time.
Live preview
live · rendered by the registry
Rendered by Kibo UI Registry on their own page — this is the component running, not a screenshot of it.Install it
npx shadcn@latest add https://www.kibo-ui.com/r/contribution-graph.jsonSource
1"use client";23import type { Day as WeekDay } from "date-fns";4import {5 differenceInCalendarDays,6 eachDayOfInterval,7 formatISO,8 getDay,9 getMonth,10 getYear,11 nextDay,12 parseISO,13 subWeeks,14} from "date-fns";15import {16 type CSSProperties,17 createContext,18 Fragment,19 type HTMLAttributes,20 type ReactNode,21 useContext,22 useMemo,23} from "react";24import { cn } from "@/lib/utils";2526export type Activity = {27 date: string;28 count: number;29 level: number;30};3132type Week = Array<Activity | undefined>;3334export type Labels = {35 months?: string[];36 weekdays?: string[];37 totalCount?: string;38 legend?: {39 less?: string;40 more?: string;41 };42};4344type MonthLabel = {45 weekIndex: number;46 label: string;47};4849const DEFAULT_MONTH_LABELS = [50 "Jan",51 "Feb",52 "Mar",53 "Apr",54 "May",55 "Jun",56 "Jul",57 "Aug",58 "Sep",59 "Oct",60 "Nov",61 "Dec",62];6364const DEFAULT_LABELS: Labels = {65 months: DEFAULT_MONTH_LABELS,66 weekdays: ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"],67 totalCount: "{{count}} activities in {{year}}",68 legend: {69 less: "Less",70 more: "More",71 },72};7374type ContributionGraphContextType = {75 data: Activity[];76 weeks: Week[];77 blockMargin: number;78 blockRadius: number;79 blockSize: number;80 fontSize: number;81 labels: Labels;82 labelHeight: number;83 maxLevel: number;84 totalCount: number;85 weekStart: WeekDay;86 year: number;87 width: number;88 height: number;89};9091const ContributionGraphContext =92 createContext<ContributionGraphContextType | null>(null);9394const useContributionGraph = () => {95 const context = useContext(ContributionGraphContext);9697 if (!context) {98 throw new Error(99 "ContributionGraph components must be used within a ContributionGraph"100 );101 }102103 return context;104};105106const fillHoles = (activities: Activity[]): Activity[] => {107 if (activities.length === 0) {108 return [];109 }110111 // Sort activities by date to ensure correct date range112 const sortedActivities = [...activities].sort((a, b) =>113 a.date.localeCompare(b.date)114 );115116 const calendar = new Map<string, Activity>(117 activities.map((a) => [a.date, a])118 );119120 const firstActivity = sortedActivities[0] as Activity;121 const lastActivity = sortedActivities.at(-1);122123 if (!lastActivity) {124 return [];125 }126127 return eachDayOfInterval({128 start: parseISO(firstActivity.date),129 end: parseISO(lastActivity.date),130 }).map((day) => {131 const date = formatISO(day, { representation: "date" });132133 if (calendar.has(date)) {134// … truncated
What it pulls in
npm packages
Files it writes
More from Kibo UI Registry
All 41 items| Component | Registry | Kind | Access | Installs | Command |
|---|---|---|---|---|---|
| announcementannouncement | Kibo UI Registry | Components | Free | no deps | |
| avatar-stackavatar-stack | Kibo UI Registry | Components | Free | no deps | |
| bannerbanner | Kibo UI Registry | Components | Free | 2 deps | |
| calendarcalendar | Kibo UI Registry | Components | Free | 3 deps | |
| choiceboxchoicebox | Kibo UI Registry | Components | Free | 2 deps | |
| code-blockcode-block | Kibo UI Registry | Components | Free | 5 deps · 2 files | |
| color-pickercolor-picker | Kibo UI Registry | Components | Free | 3 deps | |
| comboboxcombobox | Kibo UI Registry | Components | Free | 2 deps |
