fix: inject global CSS override styles for theme switching

This commit is contained in:
nmemmert committed 2026-01-15 16:55:30 -05:00
1 parent 03f2b1670f
commit af03bf4dc8
2 files changed
+77 -61

No files matched your search

+27 -39
View File
@@ -50,56 +50,44 @@ export default function RootLayout({
return ( return (
<html lang="en" suppressHydrationWarning={true}> <html lang="en" suppressHydrationWarning={true}>
<head> <head>
<style>{`
:root {
--bg-primary: #f8fafc;
--bg-secondary: #f1f5f9;
--text-primary: #1e293b;
--text-secondary: #64748b;
--border: #e2e8f0;
}
html.dark-mode {
--bg-primary: #0f172a;
--bg-secondary: #1e293b;
--text-primary: #f1f5f9;
--text-secondary: #cbd5e1;
--border: #334155;
background-color: #0f172a !important;
color: #f1f5f9 !important;
}
html {
background-color: #f8fafc;
color: #1e293b;
}
`}</style>
<script dangerouslySetInnerHTML={{ <script dangerouslySetInnerHTML={{
__html: ` __html: `
(function() { (function() {
const theme = localStorage.getItem('theme-mode') || 'dark'; const theme = localStorage.getItem('theme-mode') || 'dark';
const html = document.documentElement; const html = document.documentElement;
function applyTheme(t) { function injectThemeStyles(t) {
let styleTag = document.getElementById('theme-override-styles');
if (!styleTag) {
styleTag = document.createElement('style');
styleTag.id = 'theme-override-styles';
document.head.appendChild(styleTag);
}
if (t === 'dark') { if (t === 'dark') {
html.classList.add('dark-mode'); styleTag.textContent = \`
html.classList.add('dark'); * { color-scheme: dark !important; }
html.style.colorScheme = 'dark'; html, body { background-color: #0f172a !important; color: #f1f5f9 !important; }
document.body.style.backgroundColor = '#0f172a'; .bg-gradient-to-b { background: linear-gradient(to bottom, #0f172a, #1e293b) !important; }
document.body.style.color = '#f1f5f9'; div, section, main { background-color: inherit !important; }
p, span, h1, h2, h3, h4, h5, h6 { color: #f1f5f9 !important; }
input, textarea, button { background-color: #1e293b !important; color: #f1f5f9 !important; border-color: #334155 !important; }
\`;
} else if (t === 'light') { } else if (t === 'light') {
html.classList.remove('dark-mode'); styleTag.textContent = \`
html.classList.remove('dark'); * { color-scheme: light !important; }
html.style.colorScheme = 'light'; html, body { background-color: #f8fafc !important; color: #1e293b !important; }
document.body.style.backgroundColor = '#f8fafc'; .bg-gradient-to-b { background: linear-gradient(to bottom, #f8fafc, #f1f5f9) !important; }
document.body.style.color = '#1e293b'; div, section, main { background-color: inherit !important; }
} else if (t === 'system') { p, span, h1, h2, h3, h4, h5, h6 { color: #1e293b !important; }
const prefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches; input, textarea, button { background-color: #e2e8f0 !important; color: #1e293b !important; border-color: #cbd5e1 !important; }
applyTheme(prefersDark ? 'dark' : 'light'); \`;
} }
} }
applyTheme(theme); html.classList.add(theme);
html.setAttribute('data-theme', theme);
injectThemeStyles(theme);
})(); })();
` `
}} /> }} />
+50 -22
View File
@@ -24,42 +24,70 @@ export default function SettingsPage({ userEmail }: SettingsPageProps) {
} }
}, []); }, []);
const injectThemeStyles = (theme: string) => {
let styleId = 'theme-override-styles';
let styleTag = document.getElementById(styleId) as HTMLStyleElement;
if (!styleTag) {
styleTag = document.createElement('style');
styleTag.id = styleId;
styleTag.setAttribute('data-theme-injected', 'true');
document.head.appendChild(styleTag);
}
if (theme === 'dark') {
styleTag.textContent = `
* { color-scheme: dark !important; }
html, body { background-color: #0f172a !important; color: #f1f5f9 !important; }
.dark\\:from-slate-900, .from-slate-50, .from-slate-100 { background-color: #0f172a !important; }
.dark\\:to-slate-800, .to-slate-100 { background-color: #1e293b !important; }
div, section, main { background-color: inherit !important; }
p, span, h1, h2, h3, h4, h5, h6 { color: #f1f5f9 !important; }
input, textarea, button { background-color: #1e293b !important; color: #f1f5f9 !important; border-color: #334155 !important; }
button { background-color: #334155 !important; color: #f1f5f9 !important; }
button:hover { background-color: #475569 !important; }
`;
} else if (theme === 'light') {
styleTag.textContent = `
* { color-scheme: light !important; }
html, body { background-color: #f8fafc !important; color: #1e293b !important; }
.from-slate-50, .from-slate-100, .dark\\:from-slate-900 { background-color: #f8fafc !important; }
.to-slate-100, .dark\\:to-slate-800 { background-color: #f1f5f9 !important; }
div, section, main { background-color: inherit !important; }
p, span, h1, h2, h3, h4, h5, h6 { color: #1e293b !important; }
input, textarea, button { background-color: #e2e8f0 !important; color: #1e293b !important; border-color: #cbd5e1 !important; }
button { background-color: #cbd5e1 !important; color: #1e293b !important; }
button:hover { background-color: #bfdbfe !important; }
`;
}
};
const handleThemeChange = (newTheme: string) => { const handleThemeChange = (newTheme: string) => {
setCurrentTheme(newTheme); setCurrentTheme(newTheme);
localStorage.setItem('theme-mode', newTheme); localStorage.setItem('theme-mode', newTheme);
const html = document.documentElement; const html = document.documentElement;
const body = document.body;
if (newTheme === 'dark') { if (newTheme === 'dark') {
html.classList.add('dark-mode', 'dark'); html.classList.add('dark');
html.style.colorScheme = 'dark'; html.setAttribute('data-theme', 'dark');
body.style.backgroundColor = '#0f172a'; injectThemeStyles('dark');
body.style.color = '#f1f5f9';
document.querySelectorAll('[class*="bg-"]').forEach(el => {
if (el.classList.toString().includes('bg-slate') || el.classList.toString().includes('bg-white')) {
el.style.backgroundColor = '';
}
});
toast.success('🌙 Switched to dark theme'); toast.success('🌙 Switched to dark theme');
} else if (newTheme === 'light') { } else if (newTheme === 'light') {
html.classList.remove('dark-mode', 'dark'); html.classList.remove('dark');
html.style.colorScheme = 'light'; html.setAttribute('data-theme', 'light');
body.style.backgroundColor = '#f8fafc'; injectThemeStyles('light');
body.style.color = '#1e293b';
toast.success('☀️ Switched to light theme'); toast.success('☀️ Switched to light theme');
} else if (newTheme === 'system') { } else if (newTheme === 'system') {
const prefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches; const prefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches;
if (prefersDark) { if (prefersDark) {
html.classList.add('dark-mode', 'dark'); html.classList.add('dark');
html.style.colorScheme = 'dark'; html.setAttribute('data-theme', 'dark');
body.style.backgroundColor = '#0f172a'; injectThemeStyles('dark');
body.style.color = '#f1f5f9';
} else { } else {
html.classList.remove('dark-mode', 'dark'); html.classList.remove('dark');
html.style.colorScheme = 'light'; html.setAttribute('data-theme', 'light');
body.style.backgroundColor = '#f8fafc'; injectThemeStyles('light');
body.style.color = '#1e293b';
} }
toast.success('🔄 Using system preference'); toast.success('🔄 Using system preference');
} }