Files
nextjs-elysia-allaos/src/components/themes/active-theme.tsx
phaichayon ba1ffed211 set-up
2026-04-16 16:59:46 +07:00

72 lines
2.0 KiB
TypeScript

'use client';
import { ReactNode, createContext, useContext, useEffect, useState } from 'react';
import { DEFAULT_THEME } from './theme.config';
const COOKIE_NAME = 'active_theme';
function setThemeCookie(theme: string) {
if (typeof window === 'undefined') return;
document.cookie = `${COOKIE_NAME}=${theme}; path=/; max-age=31536000; SameSite=Lax; ${window.location.protocol === 'https:' ? 'Secure;' : ''}`;
}
type ThemeContextType = {
activeTheme: string;
setActiveTheme: (theme: string) => void;
};
const ThemeContext = createContext<ThemeContextType | undefined>(undefined);
export function ActiveThemeProvider({
children,
initialTheme
}: {
children: ReactNode;
initialTheme?: string;
}) {
const themeToUse = initialTheme || DEFAULT_THEME;
const [activeTheme, setActiveTheme] = useState<string>(themeToUse);
useEffect(() => {
// Only update if theme has changed
const currentTheme = document.documentElement.getAttribute('data-theme');
if (currentTheme !== activeTheme) {
setThemeCookie(activeTheme);
// Remove existing data-theme attribute
document.documentElement.removeAttribute('data-theme');
// Remove any theme classes from body (cleanup)
Array.from(document.body.classList)
.filter((className) => className.startsWith('theme-'))
.forEach((className) => {
document.body.classList.remove(className);
});
// Set data-theme on html element
if (activeTheme) {
document.documentElement.setAttribute('data-theme', activeTheme);
}
} else {
// Still update cookie in case it's missing
setThemeCookie(activeTheme);
}
}, [activeTheme]);
return (
<ThemeContext.Provider value={{ activeTheme, setActiveTheme }}>
{children}
</ThemeContext.Provider>
);
}
export function useThemeConfig() {
const context = useContext(ThemeContext);
if (context === undefined) {
throw new Error('useThemeConfig must be used within an ActiveThemeProvider');
}
return context;
}