abbashkyt-creator 7d8ce0e322 V0.1
2026-03-14 04:02:22 +03:00

83 lines
2.9 KiB
TypeScript

'use client'
import { useEffect, useState } from 'react'
import { motion, AnimatePresence } from 'framer-motion'
export type Theme = 'dark' | 'light'
const STORAGE_KEY = 'ghost-theme'
export function useTheme(): [Theme, () => void] {
const [theme, setTheme] = useState<Theme>('dark')
useEffect(() => {
const stored = (localStorage.getItem(STORAGE_KEY) as Theme | null) ?? 'dark'
setTheme(stored)
document.documentElement.setAttribute('data-theme', stored)
}, [])
const toggle = () => {
const next: Theme = theme === 'dark' ? 'light' : 'dark'
setTheme(next)
document.documentElement.setAttribute('data-theme', next)
localStorage.setItem(STORAGE_KEY, next)
}
return [theme, toggle]
}
export default function ThemeToggle() {
const [theme, toggle] = useTheme()
const isLight = theme === 'light'
return (
<motion.button
onClick={toggle}
whileHover={{ scale: 1.08 }}
whileTap={{ scale: 0.90 }}
className="relative g-btn h-8 w-8 px-0 flex items-center justify-center overflow-hidden"
title={`Switch to ${isLight ? 'dark' : 'light'} mode`}
aria-label={`Switch to ${isLight ? 'dark' : 'light'} mode`}
>
<AnimatePresence mode="wait" initial={false}>
{isLight ? (
/* Moon — switch to dark */
<motion.svg
key="moon"
initial={{ rotate: -90, opacity: 0, scale: 0.5 }}
animate={{ rotate: 0, opacity: 1, scale: 1 }}
exit={{ rotate: 90, opacity: 0, scale: 0.5 }}
transition={{ duration: 0.2 }}
width="14" height="14" viewBox="0 0 24 24"
fill="none" stroke="currentColor" strokeWidth="2"
strokeLinecap="round" strokeLinejoin="round"
>
<path d="M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z" />
</motion.svg>
) : (
/* Sun — switch to light */
<motion.svg
key="sun"
initial={{ rotate: 90, opacity: 0, scale: 0.5 }}
animate={{ rotate: 0, opacity: 1, scale: 1 }}
exit={{ rotate: -90, opacity: 0, scale: 0.5 }}
transition={{ duration: 0.2 }}
width="14" height="14" viewBox="0 0 24 24"
fill="none" stroke="currentColor" strokeWidth="2"
strokeLinecap="round" strokeLinejoin="round"
>
<circle cx="12" cy="12" r="5" />
<line x1="12" y1="1" x2="12" y2="3" />
<line x1="12" y1="21" x2="12" y2="23" />
<line x1="4.22" y1="4.22" x2="5.64" y2="5.64" />
<line x1="18.36" y1="18.36" x2="19.78" y2="19.78" />
<line x1="1" y1="12" x2="3" y2="12" />
<line x1="21" y1="12" x2="23" y2="12" />
<line x1="4.22" y1="19.78" x2="5.64" y2="18.36" />
<line x1="18.36" y1="5.64" x2="19.78" y2="4.22" />
</motion.svg>
)}
</AnimatePresence>
</motion.button>
)
}