Skip to content

Commit 424c64a

Browse files
ManaiakalaniCopilot
andcommitted
feat: add light/dark mode toggle with system preference detection
- CSS custom properties for all theme-aware colors - Smooth 0.3s transitions between light and dark themes - Toggle button (moon/sun) in header with frosted glass effect - Persists preference in localStorage, respects prefers-color-scheme - Inline head script prevents flash of wrong theme on load - Dark palette: deep navy backgrounds with warm light text - Responsive toggle sizing for mobile Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent 688946b commit 424c64a

File tree

3 files changed

+117
-9
lines changed

3 files changed

+117
-9
lines changed

index.html

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,16 @@
3838
<!-- External CSS -->
3939
<link rel="stylesheet" href="style.css">
4040

41+
<!-- Prevent flash: apply saved theme before paint -->
42+
<script>
43+
(function() {
44+
var t = localStorage.getItem('theme');
45+
if (t === 'dark' || (!t && window.matchMedia('(prefers-color-scheme: dark)').matches)) {
46+
document.documentElement.setAttribute('data-theme', 'dark');
47+
}
48+
})();
49+
</script>
50+
4151
<!-- Structured Data -->
4252
<script type="application/ld+json">
4353
{
@@ -67,6 +77,10 @@
6777
<h1>MANAIAKALANI</h1>
6878
<p id="typing-effect"></p>
6979
</div>
80+
<button class="theme-toggle" aria-label="Toggle dark mode">
81+
<i class="fas fa-moon"></i>
82+
<i class="fas fa-sun"></i>
83+
</button>
7084
</header>
7185

7286
<!-- About Me Section -->

script.js

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,22 @@
1+
// Theme Toggle
2+
(function() {
3+
const toggle = document.querySelector('.theme-toggle');
4+
const root = document.documentElement;
5+
const stored = localStorage.getItem('theme');
6+
const prefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches;
7+
8+
if (stored === 'dark' || (!stored && prefersDark)) {
9+
root.setAttribute('data-theme', 'dark');
10+
}
11+
12+
toggle.addEventListener('click', function() {
13+
const isDark = root.getAttribute('data-theme') === 'dark';
14+
const next = isDark ? 'light' : 'dark';
15+
root.setAttribute('data-theme', next);
16+
localStorage.setItem('theme', next);
17+
});
18+
})();
19+
120
// Typing Effect
221
const typingEffect = document.getElementById('typing-effect');
322
const typingText = "Turning problems into solutions, framing memories, and dad 24/7.";

style.css

Lines changed: 84 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,41 @@
1+
/* Custom Properties — Light Theme (default) */
2+
:root {
3+
--bg-primary: #ffffff;
4+
--bg-secondary: #f8f8f8;
5+
--bg-footer: #333333;
6+
--text-primary: #333333;
7+
--text-secondary: #555555;
8+
--text-footer: #ffffff;
9+
--text-footer-muted: #bbbbbb;
10+
--header-text: #ffffff;
11+
--accent: #ff6f61;
12+
--toggle-bg: rgba(255, 255, 255, 0.2);
13+
--toggle-hover: rgba(255, 255, 255, 0.35);
14+
--transition-speed: 0.3s;
15+
}
16+
17+
/* Dark Theme */
18+
[data-theme="dark"] {
19+
--bg-primary: #121218;
20+
--bg-secondary: #1a1a24;
21+
--bg-footer: #0d0d12;
22+
--text-primary: #e4e4e4;
23+
--text-secondary: #b0b0b0;
24+
--text-footer: #e4e4e4;
25+
--text-footer-muted: #888888;
26+
--toggle-bg: rgba(255, 255, 255, 0.1);
27+
--toggle-hover: rgba(255, 255, 255, 0.2);
28+
}
29+
130
/* General Styles */
231
body {
332
font-family: 'Doto', sans-serif;
433
margin: 0;
534
padding: 0;
635
line-height: 1.6;
7-
background-color: #fff;
8-
color: #333;
36+
background-color: var(--bg-primary);
37+
color: var(--text-primary);
38+
transition: background-color var(--transition-speed) ease, color var(--transition-speed) ease;
939
}
1040

1141
.container {
@@ -53,9 +83,10 @@ header {
5383
);
5484
background-size: 400% 400%;
5585
animation: gradient 15s ease infinite;
56-
color: #fff;
86+
color: var(--header-text);
5787
text-align: center;
5888
padding: 4rem 0;
89+
position: relative;
5990
}
6091

6192
header p {
@@ -64,22 +95,65 @@ header p {
6495
text-align: center;
6596
}
6697

98+
/* Theme Toggle */
99+
.theme-toggle {
100+
position: absolute;
101+
top: 1.2rem;
102+
right: 1.5rem;
103+
background: var(--toggle-bg);
104+
border: none;
105+
color: var(--header-text);
106+
font-size: 1.2rem;
107+
width: 2.6rem;
108+
height: 2.6rem;
109+
border-radius: 50%;
110+
cursor: pointer;
111+
display: flex;
112+
align-items: center;
113+
justify-content: center;
114+
transition: background var(--transition-speed) ease, transform var(--transition-speed) ease;
115+
backdrop-filter: blur(4px);
116+
-webkit-backdrop-filter: blur(4px);
117+
}
118+
119+
.theme-toggle:hover {
120+
background: var(--toggle-hover);
121+
transform: scale(1.1);
122+
}
123+
124+
.theme-toggle:active {
125+
transform: scale(0.95);
126+
}
127+
128+
.theme-toggle .fa-sun { display: none; }
129+
.theme-toggle .fa-moon { display: inline; }
130+
131+
[data-theme="dark"] .theme-toggle .fa-sun { display: inline; }
132+
[data-theme="dark"] .theme-toggle .fa-moon { display: none; }
133+
67134
/* About Section */
68135
#about {
69136
padding: 4rem 0;
70-
background-color: #f8f8f8;
137+
background-color: var(--bg-secondary);
138+
transition: background-color var(--transition-speed) ease;
71139
}
72140

73141
.about-text {
74142
margin-top: 2rem;
75143
}
76144

145+
.about-text p {
146+
color: var(--text-primary);
147+
transition: color var(--transition-speed) ease;
148+
}
149+
77150
/* Footer */
78151
footer {
79-
background-color: #333;
80-
color: #fff;
152+
background-color: var(--bg-footer);
153+
color: var(--text-footer);
81154
text-align: center;
82155
padding: 2rem 0;
156+
transition: background-color var(--transition-speed) ease;
83157
}
84158

85159
.social-icons {
@@ -89,21 +163,21 @@ footer {
89163
}
90164

91165
.social-icons a {
92-
color: #fff;
166+
color: var(--text-footer);
93167
font-size: 1.8rem;
94168
margin: 0 1rem;
95169
transition: transform 0.3s ease, color 0.3s ease;
96170
}
97171

98172
.social-icons a:hover {
99173
transform: scale(1.2);
100-
color: #ff6f61;
174+
color: var(--accent);
101175
}
102176

103177
.footer-text {
104178
margin-top: 1rem;
105179
font-size: 1rem;
106-
color: #bbb;
180+
color: var(--text-footer-muted);
107181
}
108182

109183
/* Gradient Animation */
@@ -120,4 +194,5 @@ footer {
120194
header p { font-size: 1.1rem; }
121195
.container { width: 90%; }
122196
.social-icons a { font-size: 1.5rem; margin: 0 0.6rem; }
197+
.theme-toggle { top: 0.8rem; right: 0.8rem; width: 2.2rem; height: 2.2rem; font-size: 1rem; }
123198
}

0 commit comments

Comments
 (0)