Skip to content

Commit e0566a8

Browse files
feat(ui): improve contributors and dashboard light mode (JhaSourav07#520)
* feat: add dark/light theme support and refine navbar * fix: improve theme consistency and dashboard UI states * improve documentation page visual hierarchy and theme consistency * Improve dark theme contrast and UI surface hierarchy * feat: improve dashboard light mode UI and contrast * feat(ui): improve dashboard and contributors light mode * fix(ui): resolve navbar hydration mismatch
1 parent 487e59d commit e0566a8

29 files changed

Lines changed: 464 additions & 304 deletions

app/(root)/dashboard/[username]/page.tsx

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -83,8 +83,7 @@ export default async function DashboardPage({
8383
<RefreshButton username={username} />
8484
<Link
8585
href="/"
86-
aria-label="Generate your own dashboard"
87-
className="flex items-center gap-2 rounded-xl border border-[rgba(255,255,255,0.15)] bg-black px-4 py-2 text-sm font-semibold text-white transition-all duration-200 hover:bg-white/5 active:scale-[0.98]"
86+
className="flex items-center gap-2 rounded-xl border border-black/10 dark:border-[rgba(255,255,255,0.15)] bg-black dark:bg-black px-4 py-2 text-sm font-semibold text-white dark:text-white transition-all duration-200 hover:bg-gray-200 dark:hover:bg-white/10 active:scale-[0.98]"
8887
>
8988
<svg
9089
xmlns="http://www.w3.org/2000/svg"

app/(root)/dashboard/error.tsx

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,29 +11,29 @@ export default function DashboardError({
1111
reset: () => void;
1212
}) {
1313
useEffect(() => {
14-
// Log the error to an error reporting service
1514
console.error(error);
1615
}, [error]);
1716

1817
const isRateLimit = error.message.includes('API limit') || error.message.includes('rate limit');
18+
1919
const isNotFound = error.message.includes('not found');
2020

2121
return (
2222
<div className="min-h-[80vh] flex flex-col items-center justify-center p-6 text-center">
23-
<div className="p-8 rounded-3xl bg-white/5 border border-white/10 backdrop-blur-xl max-w-md w-full relative overflow-hidden">
24-
<div className="absolute -top-20 -right-20 w-40 h-40 bg-pink-500/20 blur-[60px] rounded-full" />
23+
<div className="p-8 rounded-3xl bg-white/80 border border-black/10 backdrop-blur-xl dark:bg-white/5 dark:border-white/10 max-w-md w-full relative overflow-hidden shadow-xl dark:shadow-none">
24+
<div className="absolute -top-20 -right-20 w-40 h-40 bg-pink-400/10 dark:bg-pink-500/20 blur-[60px] rounded-full" />
2525

2626
<h2 className="text-4xl mb-4">{isNotFound ? '🕵️‍♂️' : isRateLimit ? '⏳' : '⚠️'}</h2>
2727

28-
<h1 className="text-2xl font-bold text-white mb-2">
28+
<h1 className="text-2xl font-bold text-gray-900 dark:text-white mb-2">
2929
{isNotFound
3030
? 'User Not Found'
3131
: isRateLimit
3232
? 'API Limit Reached'
3333
: 'Something went wrong'}
3434
</h1>
3535

36-
<p className="text-gray-400 mb-8 leading-relaxed">
36+
<p className="text-gray-600 dark:text-gray-400 mb-8 leading-relaxed">
3737
{isNotFound
3838
? "We couldn't find a GitHub user with that username. Please check the spelling and try again."
3939
: isRateLimit
@@ -44,10 +44,11 @@ export default function DashboardError({
4444
<div className="flex flex-col gap-3">
4545
<button
4646
onClick={() => reset()}
47-
className="w-full py-3 rounded-xl bg-white/10 hover:bg-white/20 text-white font-medium transition-colors"
47+
className="w-full py-3 rounded-xl bg-black text-white hover:bg-zinc-800 dark:bg-white/10 dark:hover:bg-white/20 dark:text-white font-medium transition-colors"
4848
>
4949
Try again
5050
</button>
51+
5152
<Link href="/">
5253
<button className="w-full py-3 rounded-xl bg-gradient-to-r from-cyan-500 to-purple-600 text-white font-bold shadow-lg hover:shadow-cyan-500/25 transition-all">
5354
Go back home

app/(root)/dashboard/layout.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import { Toaster } from 'sonner';
33

44
export default function DashboardLayout({ children }: { children: ReactNode }) {
55
return (
6-
<div className="min-h-screen bg-transparent text-white selection:bg-cyan-500/30 font-sans">
6+
<div className="min-h-screen bg-transparent text-gray-900 dark:text-white selection:bg-cyan-500/30 font-sans">
77
<main className="max-w-[1600px] mx-auto min-h-screen">{children}</main>
88

99
<Toaster />

app/components/CustomizeCTA.tsx

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ export function CustomizeCTA() {
1111
transition={{ duration: 0.5, ease: 'easeOut' }}
1212
className="max-w-4xl mx-auto mb-16"
1313
>
14-
<div className="group relative rounded-[2rem] border border-white/5 bg-[#0a0a0a] overflow-hidden transition-all duration-700 hover:border-white/10">
14+
<div className="group relative rounded-[2rem] border border-black/10 bg-white overflow-hidden transition-all duration-700 hover:border-black/20 dark:border-white/5 dark:bg-[#0a0a0a] dark:hover:border-white/10">
1515
{/* Hover glow layer */}
1616
<div className="absolute inset-0 bg-gradient-to-br from-emerald-500/20 to-purple-500/20 opacity-0 group-hover:opacity-100 transition-opacity duration-700 blur-2xl pointer-events-none" />
1717

@@ -24,18 +24,18 @@ export function CustomizeCTA() {
2424
<p className="text-xs font-bold uppercase tracking-[0.25em] text-emerald-400 mb-3">
2525
Customization Studio
2626
</p>
27-
<h2 className="text-2xl md:text-3xl font-extrabold text-white tracking-tight mb-3 leading-snug">
27+
<h2 className="text-2xl md:text-3xl font-extrabold text-black dark:text-white tracking-tight mb-3 leading-snug">
2828
Want to fine-tune your monolith?
2929
</h2>
30-
<p className="text-gray-500 text-sm leading-relaxed max-w-lg">
30+
<p className="text-gray-600 dark:text-gray-400 text-sm leading-relaxed max-w-lg">
3131
Dial in every pixel — swap accent colors, try a dark or neon theme, toggle logarithmic
3232
height scaling, and preview changes live before you paste a single line.
3333
</p>
3434
</div>
3535

3636
<div className="shrink-0">
3737
<Link href="/customize" id="open-customization-studio-cta">
38-
<span className="relative inline-flex items-center gap-2 px-4 md:px-7 py-4 rounded-2xl font-bold text-sm text-black bg-white hover:scale-[1.03] active:scale-[0.97] transition-transform duration-200 shadow-[0_0_30px_-4px_rgba(255,255,255,0.25)] cursor-pointer select-none">
38+
<span className="relative inline-flex items-center gap-2 px-4 md:px-7 py-4 rounded-2xl border border-black/10 dark:border-white/10 font-bold text-sm text-black dark:text-black bg-gray-100 dark:bg-white hover:bg-gray-200 dark:hover:bg-zinc-100 hover:scale-[1.03] active:scale-[0.97] transition-all duration-200 shadow-[0_0_30px_-4px_rgba(255,255,255,0.12)] cursor-pointer select-none">
3939
{/* Button shimmer */}
4040
<span
4141
aria-hidden="true"

app/components/Footer.tsx

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import Link from 'next/link';
22

33
export function Footer() {
44
return (
5-
<footer className="mt-12 border-t border-white/5 pt-8 text-sm text-white/30">
5+
<footer className="mt-12 border-t border-black/10 dark:border-white/5 pt-8 text-sm text-zinc-600 dark:text-white/30 transition-colors">
66
<div className="flex flex-col items-center justify-between gap-6 md:flex-row">
77
{/* LEFT */}
88
<p className="text-center md:text-left">
@@ -11,15 +11,18 @@ export function Footer() {
1111

1212
{/* RIGHT */}
1313
<div className="flex items-center gap-8">
14-
<Link href="/contributors" className="transition-colors hover:text-white">
14+
<Link
15+
href="/contributors"
16+
className="transition-colors hover:text-black dark:hover:text-white"
17+
>
1518
Contributors
1619
</Link>
1720

1821
<a
1922
href="https://github.com/JhaSourav07/commitpulse/blob/main/README.md"
2023
target="_blank"
2124
rel="noreferrer"
22-
className="transition-colors hover:text-white"
25+
className="transition-colors hover:text-black dark:hover:text-white"
2326
>
2427
Documentation
2528
</a>

app/components/navbar.tsx

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
import { useEffect, useState } from 'react';
44
import Link from 'next/link';
5-
import { Menu, X, Activity } from 'lucide-react';
5+
import { Menu, X, Activity, Moon, Sun } from 'lucide-react';
66
import { useGlowEffect } from '@/hooks/useGlowEffect';
77

88
function GithubMark() {
@@ -22,9 +22,25 @@ const NAV_LINKS = [
2222

2323
export default function Navbar() {
2424
const [open, setOpen] = useState(false);
25+
26+
const [isDark, setIsDark] = useState(() => {
27+
if (typeof window === 'undefined') return true;
28+
29+
return localStorage.getItem('theme') !== 'light';
30+
});
31+
2532
const { shellRef, shellVars, handleMouseEnter, handleMouseMove, handleMouseLeave } =
2633
useGlowEffect();
2734

35+
useEffect(() => {
36+
document.documentElement.classList.toggle('dark', isDark);
37+
localStorage.setItem('theme', isDark ? 'dark' : 'light');
38+
}, [isDark]);
39+
40+
const toggleTheme = () => {
41+
setIsDark((prev) => !prev);
42+
};
43+
2844
useEffect(() => {
2945
const mediaQuery = window.matchMedia('(min-width: 768px)');
3046

@@ -102,6 +118,15 @@ export default function Navbar() {
102118
</Link>
103119

104120
<div className="hidden items-center gap-3 md:flex">
121+
<button
122+
type="button"
123+
onClick={toggleTheme}
124+
className="inline-flex h-10 w-10 items-center justify-center rounded-xl border border-white/15 bg-white/5 text-white transition hover:bg-white/10"
125+
aria-label="Toggle theme"
126+
>
127+
{isDark ? <Sun size={18} /> : <Moon size={18} />}
128+
</button>
129+
105130
{NAV_LINKS.map((link) => (
106131
<a
107132
key={link.href}
@@ -118,7 +143,7 @@ export default function Navbar() {
118143

119144
<button
120145
type="button"
121-
className="inline-flex items-center justify-center rounded-xl border border-white/15 bg-white/5 p-2 text-white/90 transition hover:bg-white/10 md:hidden"
146+
className="md:hidden inline-flex items-center justify-center rounded-xl border border-white/15 bg-white/5 p-2 text-white/90 transition hover:bg-white/10"
122147
aria-label={open ? 'Close menu' : 'Open menu'}
123148
aria-expanded={open}
124149
onClick={() => setOpen((prev) => !prev)}

app/contributors/loading.tsx

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,9 @@
11
export default function Loading() {
22
return (
3-
<div className="flex min-h-screen items-center justify-center bg-black text-white">
3+
<div className="flex min-h-screen items-center justify-center bg-white text-black dark:bg-black dark:text-white transition-colors">
44
<div className="flex flex-col items-center gap-4">
55
<div className="h-14 w-14 animate-spin rounded-full border-4 border-cyan-400 border-t-transparent" />
6-
7-
<p className="text-zinc-400">Loading contributors...</p>
6+
<p className="text-zinc-500 dark:text-zinc-400">Loading contributors...</p>{' '}
87
</div>
98
</div>
109
);

0 commit comments

Comments
 (0)