fakeshield-api / fakeshield /src /hooks /useTheme.tsx
Akash4911's picture
Production Deploy: Improved robustness and logging
66b6851
Raw
History Blame Contribute Delete
2.24 kB
import React, { createContext, useContext, useState, useEffect, type ReactNode } from 'react';
type Theme = 'dark' | 'light';
interface ThemeContextType {
theme: Theme;
toggleTheme: (event?: React.MouseEvent | MouseEvent) => void;
}
const ThemeContext = createContext<ThemeContextType>({
theme: 'dark',
toggleTheme: () => {},
});
export const useTheme = () => useContext(ThemeContext);
export const ThemeProvider = ({ children }: { children: ReactNode }) => {
const [theme, setTheme] = useState<Theme>(() => {
const saved = localStorage.getItem('fakeshield-theme');
return (saved === 'light' || saved === 'dark') ? saved : 'dark';
});
useEffect(() => {
localStorage.setItem('fakeshield-theme', theme);
document.documentElement.setAttribute('data-theme', theme);
}, [theme]);
const toggleTheme = (event?: React.MouseEvent | MouseEvent) => {
const isAppearanceTransition = (document as any).startViewTransition &&
!window.matchMedia('(prefers-reduced-motion: reduce)').matches;
if (!isAppearanceTransition) {
setTheme(prev => (prev === 'dark' ? 'light' : 'dark'));
return;
}
const x = event ? (event instanceof MouseEvent ? event.clientX : (event as React.MouseEvent).nativeEvent.clientX) : window.innerWidth / 2;
const y = event ? (event instanceof MouseEvent ? event.clientY : (event as React.MouseEvent).nativeEvent.clientY) : window.innerHeight / 2;
const endRadius = Math.hypot(
Math.max(x, window.innerWidth - x),
Math.max(y, window.innerHeight - y)
);
document.documentElement.setAttribute('data-theme-transition', 'true');
document.documentElement.style.setProperty('--x', x + 'px');
document.documentElement.style.setProperty('--y', y + 'px');
document.documentElement.style.setProperty('--r', endRadius + 'px');
const transition = (document as any).startViewTransition(async () => {
setTheme(prev => (prev === 'dark' ? 'light' : 'dark'));
});
transition.finished.finally(() => {
document.documentElement.removeAttribute('data-theme-transition');
});
};
return (
<ThemeContext.Provider value={{ theme, toggleTheme }}>
{children}
</ThemeContext.Provider>
);
};