95 lines
2.8 KiB
TypeScript
95 lines
2.8 KiB
TypeScript
"use client";
|
|
|
|
import { useState, useEffect } from 'react'
|
|
import { useTheme } from 'next-themes'
|
|
|
|
const themes = ['system', 'light', 'dark'] as const
|
|
|
|
const ThemeSwitch = () => {
|
|
const [mounted, setMounted] = useState(false)
|
|
const { theme, setTheme } = useTheme()
|
|
|
|
useEffect(() => {
|
|
setMounted(true)
|
|
}, [])
|
|
|
|
if (!mounted) return null
|
|
|
|
const next = () => {
|
|
const i = themes.indexOf(theme as (typeof themes)[number])
|
|
setTheme(themes[(i + 1) % themes.length])
|
|
}
|
|
|
|
return (
|
|
<button
|
|
onClick={next}
|
|
aria-label={`Theme: ${theme}`}
|
|
title={`Theme: ${theme}`}
|
|
style={{
|
|
position: 'fixed',
|
|
top: 'var(--space-4)',
|
|
right: 'var(--space-4)',
|
|
zIndex: 9999,
|
|
background: 'var(--surface)',
|
|
border: '1px solid var(--border)',
|
|
borderRadius: 'var(--radius-md)',
|
|
color: 'var(--fg-secondary)',
|
|
cursor: 'pointer',
|
|
padding: '8px',
|
|
display: 'grid',
|
|
placeItems: 'center',
|
|
transition: `background var(--duration-fast) var(--ease-out),
|
|
border-color var(--duration-fast) var(--ease-out),
|
|
color var(--duration-fast) var(--ease-out)`,
|
|
}}
|
|
onMouseEnter={e => {
|
|
e.currentTarget.style.background = 'var(--surface-hover)'
|
|
e.currentTarget.style.borderColor = 'var(--border-strong)'
|
|
e.currentTarget.style.color = 'var(--fg)'
|
|
}}
|
|
onMouseLeave={e => {
|
|
e.currentTarget.style.background = 'var(--surface)'
|
|
e.currentTarget.style.borderColor = 'var(--border)'
|
|
e.currentTarget.style.color = 'var(--fg-secondary)'
|
|
}}
|
|
>
|
|
<svg
|
|
width="18"
|
|
height="18"
|
|
viewBox="0 0 24 24"
|
|
fill="none"
|
|
stroke="currentColor"
|
|
strokeWidth="1.75"
|
|
strokeLinecap="round"
|
|
strokeLinejoin="round"
|
|
>
|
|
{theme === 'dark' ? (
|
|
// Moon
|
|
<path d="M21 12.79A9 9 0 1 1 11.21 3a7 7 0 0 0 9.79 9.79z" />
|
|
) : theme === 'light' ? (
|
|
// Sun
|
|
<>
|
|
<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" />
|
|
</>
|
|
) : (
|
|
// Monitor (system)
|
|
<>
|
|
<rect x="2" y="3" width="20" height="14" rx="2" ry="2" />
|
|
<line x1="8" y1="21" x2="16" y2="21" />
|
|
<line x1="12" y1="17" x2="12" y2="21" />
|
|
</>
|
|
)}
|
|
</svg>
|
|
</button>
|
|
)
|
|
}
|
|
|
|
export default ThemeSwitch |