gc-wing/apps/web/src/shared/hooks/useTheme.ts

48 lines
1.0 KiB
TypeScript
Raw Normal View 히스토리

import { useState, useEffect, useCallback } from 'react';
type Theme = 'dark' | 'light';
const STORAGE_KEY = 'wing:theme';
const DEFAULT_THEME: Theme = 'dark';
function readTheme(): Theme {
try {
const raw = localStorage.getItem(STORAGE_KEY);
if (raw === 'light' || raw === 'dark') return raw;
} catch {
// storage unavailable
}
return DEFAULT_THEME;
}
function applyTheme(theme: Theme) {
document.documentElement.dataset.theme = theme;
}
export function useTheme() {
const [theme, setThemeState] = useState<Theme>(() => {
const t = readTheme();
applyTheme(t);
return t;
});
useEffect(() => {
applyTheme(theme);
}, [theme]);
const setTheme = useCallback((t: Theme) => {
setThemeState(t);
try {
localStorage.setItem(STORAGE_KEY, t);
} catch {
// quota exceeded or unavailable
}
}, []);
const toggleTheme = useCallback(() => {
setTheme(theme === 'dark' ? 'light' : 'dark');
}, [theme, setTheme]);
return { theme, setTheme, toggleTheme } as const;
}