'use client'; import { createContext, useContext, useEffect, useState, useCallback } from 'react'; type Theme = 'light'|'dark'; type Density = 'compact'|'normal'|'expanded'; const THEME_KEY = 'az-theme'; const LEGACY_THEME_KEY = 'bitforum-theme'; // 구 키 마이그레이션용 const DENSITY_KEY = 'az-density'; const ThemeContext = createContext<{ theme: Theme; toggleTheme: () => void; density: Density; setDensity: (density: Density) => void; }>({ theme: 'dark', toggleTheme: () => {}, density: 'normal', setDensity: () => {}, }); export function useThemeContext() { return useContext(ThemeContext); } // html 루트에 테마 반영 — .dark/.light 클래스(tailwind dark: variant 용) + data-theme(토큰 스위칭 용) function applyTheme(theme: Theme) { const root = document.documentElement; root.classList.toggle('dark', theme === 'dark'); root.classList.toggle('light', theme === 'light'); root.dataset.theme = theme; } export function ThemeProvider({ children }: { children: React.ReactNode }) { // 기본 다크 (D6 확정) — 첫 페인트는 app/layout.tsx 의 인라인 스크립트가 결정 (FOUC 방지) const [theme, setTheme] = useState('dark'); const [density, setDensityState] = useState('normal'); const [mounted, setMounted] = useState(false); useEffect(() => { const stored = localStorage.getItem(THEME_KEY) ?? localStorage.getItem(LEGACY_THEME_KEY); const initial: Theme = stored === 'light' ? 'light' : 'dark'; if (!localStorage.getItem(THEME_KEY) && stored) { localStorage.setItem(THEME_KEY, initial); } const storedDensity = localStorage.getItem(DENSITY_KEY); const initialDensity: Density = storedDensity === 'compact' || storedDensity === 'expanded' ? storedDensity : 'normal'; setTheme(initial); setDensityState(initialDensity); applyTheme(initial); document.documentElement.dataset.density = initialDensity; setMounted(true); }, []); const toggleTheme = useCallback(() => { setTheme((prev) => { const next = prev === 'light' ? 'dark' : 'light'; localStorage.setItem(THEME_KEY, next); applyTheme(next); return next; }); }, []); const setDensity = useCallback((next: Density) => { setDensityState(next); localStorage.setItem(DENSITY_KEY, next); document.documentElement.dataset.density = next; }, []); if (!mounted) { return <>{children}; } return ( {children} ); }