Skip to content

Commit ae074a8

Browse files
feat: add explore contributors section and contributor search functionality (JhaSourav07#535)
* Add contributor search and explore contributors section * Address PR review feedback * Remove duplicate Tailwind classes
1 parent b877a06 commit ae074a8

4 files changed

Lines changed: 108 additions & 48 deletions

File tree

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
'use client';
2+
3+
import { useState } from 'react';
4+
import Link from 'next/link';
5+
import Image from 'next/image';
6+
import { Globe } from 'lucide-react';
7+
8+
interface Contributor {
9+
id: number;
10+
login: string;
11+
avatar_url: string;
12+
contributions: number;
13+
html_url: string;
14+
}
15+
16+
export default function ContributorsSearch({ contributors }: { contributors: Contributor[] }) {
17+
const [search, setSearch] = useState('');
18+
19+
const filtered = contributors.filter((c) => c.login.toLowerCase().includes(search.toLowerCase()));
20+
21+
return (
22+
<>
23+
{/* SEARCH BAR */}
24+
<div className="mx-auto mb-10 max-w-xl">
25+
<input
26+
type="text"
27+
placeholder="Search contributors by name..."
28+
value={search}
29+
onChange={(e) => setSearch(e.target.value)}
30+
className="w-full rounded-2xl border border-black/10 bg-white/70 px-5 py-4 text-lg outline-none backdrop-blur-md transition-all duration-300 focus:border-cyan-400 focus:ring-2 focus:ring-cyan-200 dark:border-white/10 dark:bg-black/30 dark:text-white dark:focus:ring-cyan-800"
31+
/>
32+
</div>
33+
34+
{/* NO RESULTS */}
35+
{filtered.length === 0 && (
36+
<div className="flex flex-col items-center justify-center py-20 text-center">
37+
<p className="text-xl font-semibold text-zinc-600 dark:text-zinc-400">
38+
No contributors found
39+
</p>
40+
<p className="mt-2 text-sm text-zinc-500 dark:text-zinc-500">
41+
Try searching with a different name.
42+
</p>
43+
</div>
44+
)}
45+
46+
{/* GRID */}
47+
<div className="grid grid-cols-1 gap-8 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4">
48+
{filtered.map((contributor) => (
49+
<Link
50+
key={contributor.id}
51+
href={contributor.html_url}
52+
target="_blank"
53+
className="group relative overflow-hidden rounded-3xl border border-black/10 bg-white/40 dark:border-white/10 dark:bg-white/[0.04] p-7 backdrop-blur-xl shadow-[0_8px_30px_rgba(0,0,0,0.04)] dark:shadow-none transition-all duration-500 hover:-translate-y-3 hover:border-cyan-400/30 hover:bg-white/60 dark:hover:bg-white/80 dark:hover:bg-white/[0.06]"
54+
>
55+
{/* GLOW */}
56+
<div className="absolute inset-0 opacity-0 transition-opacity duration-500 group-hover:opacity-100">
57+
<div className="absolute -top-24 right-0 h-48 w-48 rounded-full bg-cyan-500/20 blur-3xl" />
58+
</div>
59+
60+
<div className="relative z-10 flex flex-col items-center text-center">
61+
{/* AVATAR */}
62+
<div className="relative">
63+
<div className="absolute inset-0 rounded-full bg-cyan-400/20 blur-2xl opacity-0 transition-opacity duration-500 group-hover:opacity-100" />
64+
<Image
65+
src={contributor.avatar_url}
66+
alt={contributor.login}
67+
width={110}
68+
height={110}
69+
className="relative rounded-full border-4 border-white/10 transition-all duration-500 group-hover:border-cyan-400/40"
70+
/>
71+
</div>
72+
73+
<h3 className="mt-6 text-2xl font-bold text-black dark:text-white">
74+
{contributor.login}
75+
</h3>
76+
77+
<p className="mt-2 text-zinc-600 dark:text-zinc-400">
78+
{contributor.contributions} contributions
79+
</p>
80+
81+
<div className="mt-6 inline-flex items-center gap-2 rounded-xl border border-black/10 bg-black/[0.03] dark:border-white/10 dark:bg-white/5 px-5 py-3 text-sm font-medium text-zinc-700 dark:text-zinc-300 transition-all duration-300 group-hover:border-cyan-400/30 group-hover:bg-cyan-400/10 group-hover:text-black dark:group-hover:text-white">
82+
<Globe className="h-4 w-4" />
83+
View Profile
84+
</div>
85+
</div>
86+
</Link>
87+
))}
88+
</div>
89+
</>
90+
);
91+
}

app/contributors/page.tsx

Lines changed: 10 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
import Link from 'next/link';
2-
import Image from 'next/image';
32
import { Globe, Sparkles, Users, GitPullRequest, ArrowRight } from 'lucide-react';
43

54
import BrandParticles from '@/components/BrandParticles';
65
import { Footer } from '@/app/components/Footer';
6+
import ContributorsSearch from './ContributorsSearch';
77

88
interface Contributor {
99
id: number;
@@ -83,6 +83,12 @@ export default async function ContributorsPage() {
8383
A collective of open-source contributors shaping the future of GitHub visualization and
8484
developer storytelling through elegant engineering and collaboration.
8585
</p>
86+
<a
87+
href="#contributors"
88+
className="mt-8 inline-flex items-center gap-2 rounded-full bg-black px-6 py-3 text-white font-medium hover:scale-105 transition-all duration-300"
89+
>
90+
Explore Contributors →
91+
</a>
8692
</section>
8793

8894
{/* STATS */}
@@ -143,7 +149,7 @@ export default async function ContributorsPage() {
143149
</p>
144150
</div>
145151

146-
<div className="rounded-3xl border border-black/10 bg-white/40 dark:border-white/10 dark:bg-white/[0.04] shadow-[0_8px_30px_rgba(0,0,0,0.04)] dark:shadow-none dark:border-white/10 dark:bg-white/[0.04] p-8 backdrop-blur-xl">
152+
<div className="rounded-3xl border border-black/10 bg-white/40 dark:border-white/10 dark:bg-white/[0.04] shadow-[0_8px_30px_rgba(0,0,0,0.04)] dark:shadow-none p-8 backdrop-blur-xl">
147153
<div className="space-y-6">
148154
{topContributors.map((contributor, index) => (
149155
<div key={contributor.id}>
@@ -178,7 +184,7 @@ export default async function ContributorsPage() {
178184
</section>
179185

180186
{/* CONTRIBUTORS GRID */}
181-
<section className="mx-auto mt-32 max-w-7xl px-6">
187+
<section className="mx-auto mt-32 max-w-7xl px-6" id="contributors">
182188
<div className="mb-16 text-center">
183189
<h2 className="text-4xl font-black text-black dark:text-white md:text-5xl">
184190
Community Contributors
@@ -189,49 +195,7 @@ export default async function ContributorsPage() {
189195
</p>
190196
</div>
191197

192-
<div className="grid grid-cols-1 gap-8 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4">
193-
{contributors.map((contributor) => (
194-
<Link
195-
key={contributor.id}
196-
href={contributor.html_url}
197-
target="_blank"
198-
className="group relative overflow-hidden rounded-3xl border border-black/10 bg-white/40 dark:border-white/10 dark:bg-white/[0.04] p-7 backdrop-blur-xl shadow-[0_8px_30px_rgba(0,0,0,0.04)] dark:shadow-none transition-all duration-500 hover:-translate-y-3 hover:border-cyan-400/30 hover:bg-white/60 dark:hover:bg-white/80 dark:hover:bg-white/[0.06]"
199-
>
200-
{/* GLOW */}
201-
<div className="absolute inset-0 opacity-0 transition-opacity duration-500 group-hover:opacity-100">
202-
<div className="absolute -top-24 right-0 h-48 w-48 rounded-full bg-cyan-500/20 blur-3xl" />
203-
</div>
204-
205-
<div className="relative z-10 flex flex-col items-center text-center">
206-
{/* AVATAR */}
207-
<div className="relative">
208-
<div className="absolute inset-0 rounded-full bg-cyan-400/20 blur-2xl opacity-0 transition-opacity duration-500 group-hover:opacity-100" />
209-
210-
<Image
211-
src={contributor.avatar_url}
212-
alt={contributor.login}
213-
width={110}
214-
height={110}
215-
className="relative rounded-full border-4 border-white/10 transition-all duration-500 group-hover:border-cyan-400/40"
216-
/>
217-
</div>
218-
219-
<h3 className="mt-6 text-2xl font-bold text-black dark:text-white">
220-
{contributor.login}
221-
</h3>
222-
223-
<p className="mt-2 text-zinc-600 dark:text-zinc-400">
224-
{contributor.contributions} contributions
225-
</p>
226-
227-
<div className="mt-6 inline-flex items-center gap-2 rounded-xl border border-black/10 bg-black/[0.03] dark:border-white/10 dark:bg-white/5 px-5 py-3 text-sm font-medium text-zinc-700 dark:text-zinc-300 transition-all duration-300 group-hover:border-cyan-400/30 group-hover:bg-cyan-400/10 group-hover:text-white">
228-
<Globe className="h-4 w-4" />
229-
View Profile
230-
</div>
231-
</div>
232-
</Link>
233-
))}
234-
</div>
198+
<ContributorsSearch contributors={contributors} />
235199
</section>
236200

237201
{/* CTA */}

app/customize/page.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,7 @@ export default function CustomizePage(): ReactElement {
158158
<div className="absolute bottom-0 left-1/2 w-[30%] h-[30%] bg-blue-500/5 blur-[120px] rounded-full" />
159159
</div>
160160

161-
<div className="relative z-10 max-w-[1400px] mx-auto px-6 py-8">
161+
<div className="relative z-10 max-w-7xl mx-auto px-6 py-8">
162162
{/* ── Top Bar ───────────────────────────────────────────────────────── */}
163163
<motion.div
164164
initial={{ opacity: 0, y: -10 }}

app/globals.css

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,9 @@
55
--font-sans: 'Inter', ui-sans-serif, system-ui;
66
--breakpoint-xs: 26rem;
77
}
8-
8+
html {
9+
scroll-behavior: smooth;
10+
}
911
@layer utilities {
1012
.slider::-webkit-slider-thumb {
1113
appearance: none;
@@ -127,3 +129,6 @@ body {
127129
background-color: #00ffaa;
128130
color: #0d1117;
129131
}
132+
/* html {
133+
scroll-behavior: smooth;
134+
} */

0 commit comments

Comments
 (0)