GitHub Graph
v3cn/githubFreeComponent
A GitHub component for displaying contribution graph with custom styling.
Live preview
live · rendered by the registry
Rendered by v3cn on their own page — this is the component running, not a screenshot of it.Install it
npx shadcn@latest add https://v3cn.vineet.pro/r/github.jsonSource
1"use client";23import { Activity, ActivityCalendar } from "react-activity-calendar";4import { memo, useCallback, useEffect, useState } from "react";56import { useTheme } from "next-themes";78/**9 * Props for the GitHub contribution graph component10 */11type GithubGraphProps = {12 /** GitHub username to fetch contributions for */13 username: string;14 /** Margin between contribution blocks in pixels */15 blockMargin?: number;16 /** Custom color palette for light theme */17 lightColorPalette?: string[];18 /** Custom color palette for dark theme */19 darkColorPalette?: string[];20};2122/**23 * API response type for GitHub contributions24 */25type GithubApiResponse = {26 data: Activity[];27 error?: string;28};2930const DEFAULT_LIGHT_PALETTE = [31 "#ebedf0",32 "#9be9a8",33 "#40c463",34 "#30a14e",35 "#216e39",36];3738const DEFAULT_DARK_PALETTE = [39 "#1e1e2f",40 "#5a3e7a",41 "#7e5aa2",42 "#a87cc3",43 "#d9a9e6",44];4546/**47 * GitHub contribution graph component that displays user's contribution activity48 */49export const GithubGraph = memo(({50 username,51 blockMargin,52 lightColorPalette = DEFAULT_LIGHT_PALETTE,53 darkColorPalette = DEFAULT_DARK_PALETTE,54}: GithubGraphProps) => {55 const [contribution, setContribution] = useState<Activity[]>([]);56 const [loading, setIsLoading] = useState<boolean>(true);57 const [error, setError] = useState<string | null>(null);58 const { theme } = useTheme();5960 const fetchData = useCallback(async () => {61 try {62 setError(null);63 setIsLoading(true);64 const contributions = await fetchContributionData(username);65 setContribution(contributions);66 } catch (error) {67 setError(error instanceof Error ? error.message : "Failed to fetch contribution data");68 setContribution([]);69 } finally {70 setIsLoading(false);71 }72 }, [username]);7374 useEffect(() => {75 fetchData();76 }, [fetchData]);7778 const label = {79 totalCount: `{{count}} contributions in the last year`,80 };8182 if (error) {83 return (84 <div className="text-red-500 p-4 text-center">85 Error: {error}86 </div>87 );88 }8990 return (91 <div className="relative">92 {loading && (93 <div className="absolute inset-0 flex items-center justify-center">94 <div className="animate-spin rounded-full h-8 w-8 border-b-2 border-gray-900 dark:border-white"></div>95 </div>96 )}97 <ActivityCalendar98 data={contribution}99 maxLevel={4}100 blockMargin={blockMargin ?? 2}101 loading={loading}102// … truncated
Files it writes
More from v3cn
All 6 items| Component | Registry | Kind | Access | Installs | Command |
|---|---|---|---|---|---|
| Cursorcursor | v3cn | Components | Free | no deps | |
| Discord Presencediscord | v3cn | Components | Free | no deps |
