UMBRA/frontend/src/hooks/useTheme.ts
Kyle Pope f9359bd78a Recreate accent style tag if removed during page init
The <style id="umbra-accent"> tag injected by index.html gets removed
during page initialization. useTheme now defensively recreates the tag
if it's missing, ensuring color changes from the settings page work.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-12 20:39:37 +08:00

51 lines
1.5 KiB
TypeScript

import { useEffect } from 'react';
import { useSettings } from './useSettings';
const ACCENT_PRESETS: Record<string, { h: number; s: number; l: number }> = {
cyan: { h: 187, s: 85.7, l: 53.3 },
blue: { h: 217, s: 91.2, l: 59.8 },
purple: { h: 258, s: 89.5, l: 66.3 },
orange: { h: 21, s: 94.6, l: 53.3 },
green: { h: 142, s: 70.6, l: 45.3 },
red: { h: 0, s: 84.2, l: 60.2 },
pink: { h: 330, s: 81.2, l: 60.4 },
yellow: { h: 48, s: 83.3, l: 47.5 },
};
export function useTheme() {
const { settings } = useSettings();
// Only apply accent color once settings have loaded from the API.
// Creates or updates a <style id="umbra-accent"> tag with !important vars.
// The tag may be removed during page init, so always recreate if missing.
useEffect(() => {
if (!settings) return;
const colorName = settings.accent_color || 'cyan';
const preset = ACCENT_PRESETS[colorName];
if (!preset) return;
const h = preset.h.toString();
const s = `${preset.s}%`;
const l = `${preset.l}%`;
const css = `:root{--accent-h:${h} !important;--accent-s:${s} !important;--accent-l:${l} !important}`;
let el = document.getElementById('umbra-accent');
if (!el) {
el = document.createElement('style');
el.id = 'umbra-accent';
document.head.appendChild(el);
}
el.textContent = css;
try {
localStorage.setItem('umbra-accent-color', JSON.stringify({ h, s, l }));
} catch {}
}, [settings]);
return {
accentColor: settings?.accent_color || 'cyan',
presets: ACCENT_PRESETS,
};
}