Files
monie-web/src/components/ThemeToggle.tsx
T
denis 42b3d16853
Deploy monie-web to prod (kaniko) / build-and-deploy (push) Successful in 10m51s
chore: initialize project
2026-04-12 17:19:08 +03:00

82 lines
2.2 KiB
TypeScript

import { useEffect, useState } from 'react'
type ThemeMode = 'light' | 'dark' | 'auto'
function getInitialMode(): ThemeMode {
if (typeof window === 'undefined') {
return 'auto'
}
const stored = window.localStorage.getItem('theme')
if (stored === 'light' || stored === 'dark' || stored === 'auto') {
return stored
}
return 'auto'
}
function applyThemeMode(mode: ThemeMode) {
const prefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches
const resolved = mode === 'auto' ? (prefersDark ? 'dark' : 'light') : mode
document.documentElement.classList.remove('light', 'dark')
document.documentElement.classList.add(resolved)
if (mode === 'auto') {
document.documentElement.removeAttribute('data-theme')
} else {
document.documentElement.setAttribute('data-theme', mode)
}
document.documentElement.style.colorScheme = resolved
}
export default function ThemeToggle() {
const [mode, setMode] = useState<ThemeMode>('auto')
useEffect(() => {
const initialMode = getInitialMode()
setMode(initialMode)
applyThemeMode(initialMode)
}, [])
useEffect(() => {
if (mode !== 'auto') {
return
}
const media = window.matchMedia('(prefers-color-scheme: dark)')
const onChange = () => applyThemeMode('auto')
media.addEventListener('change', onChange)
return () => {
media.removeEventListener('change', onChange)
}
}, [mode])
function toggleMode() {
const nextMode: ThemeMode =
mode === 'light' ? 'dark' : mode === 'dark' ? 'auto' : 'light'
setMode(nextMode)
applyThemeMode(nextMode)
window.localStorage.setItem('theme', nextMode)
}
const label =
mode === 'auto'
? 'Theme mode: auto (system). Click to switch to light mode.'
: `Theme mode: ${mode}. Click to switch mode.`
return (
<button
type="button"
onClick={toggleMode}
aria-label={label}
title={label}
className="rounded-full border border-[var(--chip-line)] bg-[var(--chip-bg)] px-3 py-1.5 text-sm font-semibold text-[var(--sea-ink)] shadow-[0_8px_22px_rgba(30,90,72,0.08)] transition hover:-translate-y-0.5"
>
{mode === 'auto' ? 'Auto' : mode === 'dark' ? 'Dark' : 'Light'}
</button>
)
}