feat: add theme toggle to mobile navigation

- Add theme toggle button at bottom of mobile nav
- Share toggleTheme function between desktop and mobile
- Style mobile toggle to match nav item appearance

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Ricardo
2026-02-01 15:01:24 +01:00
parent ba94a6e5c8
commit ed2044dd8b
2 changed files with 54 additions and 5 deletions
+25 -5
View File
@@ -212,6 +212,19 @@
</div> </div>
</div> </div>
<a href="/interactions/">Interactions</a> <a href="/interactions/">Interactions</a>
{# Mobile theme toggle #}
<button type="button" class="mobile-theme-toggle" aria-label="Toggle dark mode">
<span class="theme-label">Theme</span>
<span class="theme-icons">
<svg class="sun-icon" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<circle cx="12" cy="12" r="5"/>
<path d="M12 1v2M12 21v2M4.22 4.22l1.42 1.42M18.36 18.36l1.42 1.42M1 12h2M21 12h2M4.22 19.78l1.42-1.42M18.36 5.64l1.42-1.42"/>
</svg>
<svg class="moon-icon" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<path d="M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z"/>
</svg>
</span>
</button>
</nav> </nav>
</header> </header>
@@ -281,13 +294,20 @@
}); });
} }
// Theme toggle functionality // Theme toggle functionality (desktop and mobile)
const themeToggle = document.getElementById('theme-toggle'); function toggleTheme() {
if (themeToggle) {
themeToggle.addEventListener('click', () => {
const isDark = document.documentElement.classList.toggle('dark'); const isDark = document.documentElement.classList.toggle('dark');
localStorage.setItem('theme', isDark ? 'dark' : 'light'); localStorage.setItem('theme', isDark ? 'dark' : 'light');
}); }
const themeToggle = document.getElementById('theme-toggle');
if (themeToggle) {
themeToggle.addEventListener('click', toggleTheme);
}
const mobileThemeToggle = document.querySelector('.mobile-theme-toggle');
if (mobileThemeToggle) {
mobileThemeToggle.addEventListener('click', toggleTheme);
} }
// Link prefetching on mouseover/touchstart for faster navigation // Link prefetching on mouseover/touchstart for faster navigation
+29
View File
@@ -150,6 +150,35 @@
@apply hidden; @apply hidden;
} }
/* Mobile theme toggle */
.mobile-theme-toggle {
@apply flex items-center justify-between w-full px-4 py-3 text-surface-600 dark:text-surface-400 hover:bg-surface-100 dark:hover:bg-surface-800 hover:text-primary-600 dark:hover:text-primary-400 transition-colors bg-transparent border-none text-base text-left cursor-pointer border-t border-surface-200 dark:border-surface-700;
}
.mobile-theme-toggle .theme-label {
@apply font-normal;
}
.mobile-theme-toggle .theme-icons {
@apply flex items-center;
}
.mobile-theme-toggle .sun-icon {
@apply hidden;
}
.mobile-theme-toggle .moon-icon {
@apply block;
}
.dark .mobile-theme-toggle .sun-icon {
@apply block;
}
.dark .mobile-theme-toggle .moon-icon {
@apply hidden;
}
/* Container */ /* Container */
.container { .container {
@apply max-w-5xl mx-auto px-4; @apply max-w-5xl mx-auto px-4;