Skip to content

Commit 43a3744

Browse files
feat: implement Vercel-style black/white monochrome theme with dark mode default and theme toggle
1 parent 783129c commit 43a3744

4 files changed

Lines changed: 164 additions & 57 deletions

File tree

src/data/cv.json

Lines changed: 2 additions & 2 deletions
Large diffs are not rendered by default.

src/layouts/BaseLayout.astro

Lines changed: 85 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,12 @@ const navItems = [
4040
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700;800&family=JetBrains+Mono:wght@400;500;700&display=swap" rel="stylesheet">
4141
<title>{title}</title>
4242
<meta name="description" content={description} />
43+
<script is:inline>
44+
const savedTheme = localStorage.getItem('theme');
45+
const systemDark = window.matchMedia('(prefers-color-scheme: dark)').matches;
46+
const initialTheme = savedTheme || (systemDark ? 'dark' : 'dark'); // Default to dark
47+
document.documentElement.setAttribute('data-theme', initialTheme);
48+
</script>
4349
</head>
4450
<body>
4551
<header class="site-header">
@@ -54,12 +60,29 @@ const navItems = [
5460
);
5561
})}
5662
</nav>
63+
64+
<button id="theme-toggle-btn" class="theme-toggle-btn" aria-label="Toggle light and dark theme">
65+
<span class="sun-icon">☀️</span>
66+
<span class="moon-icon">🌙</span>
67+
</button>
5768
</div>
5869
</header>
5970

6071
<main class="site-main">
6172
<slot />
6273
</main>
74+
75+
<script>
76+
const toggleBtn = document.getElementById('theme-toggle-btn');
77+
if (toggleBtn) {
78+
toggleBtn.addEventListener('click', () => {
79+
const currentTheme = document.documentElement.getAttribute('data-theme') || 'dark';
80+
const nextTheme = currentTheme === 'dark' ? 'light' : 'dark';
81+
document.documentElement.setAttribute('data-theme', nextTheme);
82+
localStorage.setItem('theme', nextTheme);
83+
});
84+
}
85+
</script>
6386
</body>
6487
</html>
6588

@@ -68,24 +91,25 @@ const navItems = [
6891
position: sticky;
6992
top: 0;
7093
z-index: 50;
71-
background: rgba(15, 23, 42, 0.85);
94+
background: var(--bg-glass);
7295
backdrop-filter: blur(16px);
7396
-webkit-backdrop-filter: blur(16px);
7497
border-bottom: 1px solid var(--border-glass);
7598
padding: 0.75rem 0;
99+
transition: background 0.25s ease;
76100
}
77101

78102
.header-content {
79103
display: flex;
80-
justify-content: center;
104+
justify-content: space-between;
81105
align-items: center;
82106
}
83107

84108
.nav-links {
85109
display: flex;
86-
gap: 0.5rem;
110+
gap: 0.35rem;
87111
flex-wrap: wrap;
88-
justify-content: center;
112+
align-items: center;
89113
}
90114

91115
.nav-links a {
@@ -100,16 +124,63 @@ const navItems = [
100124

101125
.nav-links a:hover {
102126
color: var(--text-main);
103-
background: rgba(255, 255, 255, 0.05);
104-
border-color: rgba(255, 255, 255, 0.08);
127+
background: rgba(255, 255, 255, 0.06);
128+
}
129+
130+
[data-theme="light"] .nav-links a:hover {
131+
background: rgba(0, 0, 0, 0.05);
105132
}
106133

107134
.nav-links a.active {
108-
color: var(--accent-blue);
109-
background: rgba(56, 189, 248, 0.12);
110-
border-color: rgba(56, 189, 248, 0.3);
135+
color: var(--text-main);
136+
background: rgba(255, 255, 255, 0.1);
137+
border-color: var(--border-glass);
111138
font-weight: 600;
112-
box-shadow: 0 0 12px rgba(56, 189, 248, 0.15);
139+
}
140+
141+
[data-theme="light"] .nav-links a.active {
142+
background: rgba(0, 0, 0, 0.06);
143+
border-color: rgba(0, 0, 0, 0.12);
144+
}
145+
146+
.theme-toggle-btn {
147+
background: rgba(255, 255, 255, 0.05);
148+
border: 1px solid var(--border-glass);
149+
border-radius: 8px;
150+
width: 36px;
151+
height: 36px;
152+
display: flex;
153+
align-items: center;
154+
justify-content: center;
155+
cursor: pointer;
156+
transition: all 0.2s ease;
157+
}
158+
159+
[data-theme="light"] .theme-toggle-btn {
160+
background: rgba(0, 0, 0, 0.05);
161+
}
162+
163+
.theme-toggle-btn:hover {
164+
border-color: var(--border-hover);
165+
transform: scale(1.05);
166+
}
167+
168+
.sun-icon {
169+
display: none;
170+
font-size: 0.95rem;
171+
}
172+
173+
.moon-icon {
174+
display: block;
175+
font-size: 0.95rem;
176+
}
177+
178+
[data-theme="light"] .sun-icon {
179+
display: block;
180+
}
181+
182+
[data-theme="light"] .moon-icon {
183+
display: none;
113184
}
114185

115186
.site-main {
@@ -118,15 +189,14 @@ const navItems = [
118189

119190
@media (max-width: 768px) {
120191
.header-content {
121-
flex-direction: column;
122-
gap: 1rem;
192+
gap: 0.75rem;
123193
}
124194
.nav-links {
125-
gap: 0.35rem;
195+
gap: 0.25rem;
126196
}
127197
.nav-links a {
128-
font-size: 0.85rem;
129-
padding: 0.35rem 0.65rem;
198+
font-size: 0.82rem;
199+
padding: 0.3rem 0.6rem;
130200
}
131201
}
132202
</style>

src/pages/index.astro

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -240,26 +240,30 @@ const totalProjects = featuredProjects.length;
240240
}
241241

242242
.btn-primary {
243-
background: linear-gradient(135deg, #0284c7, #4f46e5);
244-
color: #ffffff;
245-
box-shadow: 0 4px 15px rgba(2, 132, 199, 0.35);
243+
background: var(--text-main);
244+
color: var(--bg-primary);
245+
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2);
246246
}
247247

248248
.btn-primary:hover {
249-
box-shadow: 0 6px 20px rgba(2, 132, 199, 0.5);
250-
transform: translateY(-2px);
251-
color: #ffffff;
249+
opacity: 0.9;
250+
transform: translateY(-1px);
251+
color: var(--bg-primary);
252252
}
253253

254254
.btn-secondary {
255-
background: rgba(255, 255, 255, 0.05);
255+
background: transparent;
256256
border: 1px solid var(--border-glass);
257257
color: var(--text-main);
258258
}
259259

260260
.btn-secondary:hover {
261-
background: rgba(255, 255, 255, 0.1);
262-
color: var(--accent-blue);
261+
border-color: var(--border-hover);
262+
background: rgba(255, 255, 255, 0.05);
263+
}
264+
265+
[data-theme="light"] .btn-secondary:hover {
266+
background: rgba(0, 0, 0, 0.04);
263267
}
264268

265269
.btn-sm {

src/styles/global.css

Lines changed: 64 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,52 @@
11
:root {
2-
/* Slate & Deep Indigo Professional Dark Theme */
3-
--bg-primary: #0f172a; /* Deep Slate Blue */
4-
--bg-surface: #1e293b; /* Elevated Surface Slate */
5-
--bg-glass: rgba(30, 41, 59, 0.75);
6-
--border-glass: rgba(255, 255, 255, 0.08);
2+
/* Default Dark Vercel Theme */
3+
--bg-primary: #000000;
4+
--bg-surface: #0a0a0a;
5+
--bg-card: rgba(18, 18, 18, 0.7);
6+
--bg-glass: rgba(10, 10, 10, 0.8);
7+
--border-glass: rgba(255, 255, 255, 0.12);
8+
--border-hover: rgba(255, 255, 255, 0.3);
79

8-
--text-main: #f8fafc; /* High-contrast Slate Light Text */
9-
--text-muted: #94a3b8; /* Soft Muted Subtitles */
10+
--text-main: #ededed;
11+
--text-muted: #a1a1a1;
12+
--text-subtle: #666666;
1013

11-
/* Refined Enterprise Accent Palette */
12-
--accent-blue: #38bdf8; /* Sky Blue Accent */
13-
--accent-indigo: #818cf8; /* Professional Indigo */
14-
--accent-teal: #2dd4bf; /* Clean Teal Accent */
15-
16-
--glow-blue: rgba(56, 189, 248, 0.18);
17-
--glow-indigo: rgba(129, 140, 248, 0.15);
14+
--accent-blue: #ffffff;
15+
--accent-indigo: #ededed;
16+
--accent-orange: #ffffff;
17+
--accent-amber: #a1a1a1;
1818

19+
--glow-blue: rgba(255, 255, 255, 0.1);
20+
--glow-indigo: rgba(255, 255, 255, 0.08);
21+
1922
--font-sans: 'Inter', system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
2023
--font-mono: 'JetBrains Mono', 'Fira Code', monospace;
24+
25+
color-scheme: dark;
26+
}
27+
28+
[data-theme="light"] {
29+
/* Minimalist Light Vercel Theme */
30+
--bg-primary: #ffffff;
31+
--bg-surface: #fafafa;
32+
--bg-card: rgba(255, 255, 255, 0.9);
33+
--bg-glass: rgba(255, 255, 255, 0.85);
34+
--border-glass: rgba(0, 0, 0, 0.08);
35+
--border-hover: rgba(0, 0, 0, 0.25);
36+
37+
--text-main: #171717;
38+
--text-muted: #666666;
39+
--text-subtle: #999999;
40+
41+
--accent-blue: #000000;
42+
--accent-indigo: #171717;
43+
--accent-orange: #000000;
44+
--accent-amber: #666666;
45+
46+
--glow-blue: rgba(0, 0, 0, 0.05);
47+
--glow-indigo: rgba(0, 0, 0, 0.03);
48+
49+
color-scheme: light;
2150
}
2251

2352
* {
@@ -32,43 +61,43 @@ html {
3261
color: var(--text-main);
3362
scroll-behavior: smooth;
3463
line-height: 1.6;
64+
transition: background-color 0.25s ease, color 0.25s ease;
3565
}
3666

3767
body {
3868
min-height: 100vh;
3969
display: flex;
4070
flex-direction: column;
71+
background-color: var(--bg-primary);
4172
background-image:
42-
radial-gradient(circle at 15% 15%, var(--glow-blue) 0%, transparent 45%),
43-
radial-gradient(circle at 85% 85%, var(--glow-indigo) 0%, transparent 45%);
73+
radial-gradient(circle at 50% 0%, var(--glow-blue) 0%, transparent 60%);
4474
background-attachment: fixed;
4575
}
4676

4777
a {
48-
color: var(--accent-blue);
78+
color: var(--text-main);
4979
text-decoration: none;
50-
transition: color 0.2s ease, text-shadow 0.2s ease;
80+
transition: color 0.2s ease, opacity 0.2s ease;
5181
}
5282

5383
a:hover {
54-
color: #7dd3fc;
55-
text-shadow: 0 0 12px var(--glow-blue);
84+
opacity: 0.8;
5685
}
5786

5887
.glass-card {
59-
background: var(--bg-glass);
60-
backdrop-filter: blur(12px);
61-
-webkit-backdrop-filter: blur(12px);
88+
background: var(--bg-card);
89+
backdrop-filter: blur(16px);
90+
-webkit-backdrop-filter: blur(16px);
6291
border: 1px solid var(--border-glass);
63-
border-radius: 14px;
92+
border-radius: 12px;
6493
padding: 1.75rem;
65-
transition: transform 0.3s ease, border-color 0.3s ease, box-shadow 0.3s ease;
94+
transition: transform 0.25s cubic-bezier(0.16, 1, 0.3, 1), border-color 0.25s ease, box-shadow 0.25s ease;
6695
}
6796

6897
.glass-card:hover {
69-
transform: translateY(-3px);
70-
border-color: rgba(56, 189, 248, 0.35);
71-
box-shadow: 0 12px 30px -10px rgba(15, 23, 42, 0.8), 0 0 20px var(--glow-blue);
98+
transform: translateY(-2px);
99+
border-color: var(--border-hover);
100+
box-shadow: 0 12px 30px -10px rgba(0, 0, 0, 0.3);
72101
}
73102

74103
.tag-badge {
@@ -77,9 +106,13 @@ a:hover {
77106
border-radius: 9999px;
78107
font-size: 0.8rem;
79108
font-weight: 500;
80-
background: rgba(56, 189, 248, 0.1);
81-
color: var(--accent-blue);
82-
border: 1px solid rgba(56, 189, 248, 0.25);
109+
background: rgba(255, 255, 255, 0.06);
110+
color: var(--text-main);
111+
border: 1px solid var(--border-glass);
112+
}
113+
114+
[data-theme="light"] .tag-badge {
115+
background: rgba(0, 0, 0, 0.05);
83116
}
84117

85118
.container {

0 commit comments

Comments
 (0)