we're about to port the chrome-extension. everything else mostly works

This commit is contained in:
cottongin
2025-10-30 13:27:55 -04:00
parent 2db707961c
commit db2a8abe66
29 changed files with 2490 additions and 562 deletions

View File

@@ -0,0 +1,70 @@
import React, { createContext, useState, useContext, useEffect } from 'react';
const ThemeContext = createContext();
export const useTheme = () => {
const context = useContext(ThemeContext);
if (!context) {
throw new Error('useTheme must be used within a ThemeProvider');
}
return context;
};
export const ThemeProvider = ({ children }) => {
const [theme, setTheme] = useState(() => {
// Check localStorage first, then system preference
const stored = localStorage.getItem('theme');
if (stored) return stored;
return 'system'; // Default to system preference
});
useEffect(() => {
const root = window.document.documentElement;
if (theme === 'system') {
// Follow system preference
const isDark = window.matchMedia('(prefers-color-scheme: dark)').matches;
root.classList.remove('light', 'dark');
root.classList.add(isDark ? 'dark' : 'light');
localStorage.setItem('theme', 'system');
} else {
// Use explicit theme
root.classList.remove('light', 'dark');
root.classList.add(theme);
localStorage.setItem('theme', theme);
}
}, [theme]);
// Listen for system theme changes when in system mode
useEffect(() => {
if (theme !== 'system') return;
const mediaQuery = window.matchMedia('(prefers-color-scheme: dark)');
const handleChange = () => {
const root = window.document.documentElement;
root.classList.remove('light', 'dark');
root.classList.add(mediaQuery.matches ? 'dark' : 'light');
};
mediaQuery.addEventListener('change', handleChange);
return () => mediaQuery.removeEventListener('change', handleChange);
}, [theme]);
const toggleTheme = () => {
setTheme(prev => {
if (prev === 'light') return 'dark';
if (prev === 'dark') return 'system';
return 'light';
});
};
const value = {
theme,
toggleTheme,
isDark: theme === 'dark' || (theme === 'system' && window.matchMedia('(prefers-color-scheme: dark)').matches),
};
return <ThemeContext.Provider value={value}>{children}</ThemeContext.Provider>;
};