6b698c5f58
- Add CLAUDE.md with project conventions and architecture notes
- Create Navbar (sticky, backdrop blur, mobile menu) and Footer
- Build homepage sections: Hero, FeaturedProjects, Skills, CurrentWork, CallToAction
- Add /projects, /about, and /contact pages
- Create reusable ProjectCard and Badge components
- Centralise project data in content/projects.json with featured flag
- Add class-based dark mode toggle (default dark, persisted to localStorage)
- Refactor globals.css: remove conflicting prefers-color-scheme media query
- Fix two-instance ThemeToggle sync bug in Navbar
- Fix key={index} anti-pattern in timeline, stale closure in setOpen
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
45 lines
1.5 KiB
TypeScript
45 lines
1.5 KiB
TypeScript
'use client'
|
|
|
|
import { useState } from 'react'
|
|
|
|
function isDark() {
|
|
if (typeof window === 'undefined') return true
|
|
return document.documentElement.classList.contains('dark')
|
|
}
|
|
|
|
export default function ThemeToggle() {
|
|
const [dark, setDark] = useState(isDark)
|
|
|
|
function toggle() {
|
|
const next = !dark
|
|
setDark(next)
|
|
document.documentElement.classList.toggle('dark', next)
|
|
try {
|
|
localStorage.setItem('theme', next ? 'dark' : 'light')
|
|
} catch {
|
|
// ignore
|
|
}
|
|
}
|
|
|
|
return (
|
|
<button
|
|
onClick={toggle}
|
|
aria-label="Toggle theme"
|
|
className="flex h-8 w-8 items-center justify-center rounded-sm text-zinc-500 transition-colors hover:bg-zinc-100 hover:text-zinc-900 dark:hover:bg-zinc-800 dark:hover:text-zinc-100"
|
|
>
|
|
{dark ? (
|
|
// Sun — switch to light
|
|
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
|
|
<circle cx="12" cy="12" r="4" />
|
|
<path d="M12 2v2M12 20v2M4.93 4.93l1.41 1.41M17.66 17.66l1.41 1.41M2 12h2M20 12h2M4.93 19.07l1.41-1.41M17.66 6.34l1.41-1.41" />
|
|
</svg>
|
|
) : (
|
|
// Moon — switch to dark
|
|
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
|
|
<path d="M12 3a6 6 0 0 0 9 9 9 9 0 1 1-9-9Z" />
|
|
</svg>
|
|
)}
|
|
</button>
|
|
)
|
|
}
|