Fix accent color flash on refresh by eliminating CSS/JS race
Guard useTheme effect to skip when settings are undefined, preventing it from overwriting the inline script's cached color with cyan defaults. Move CSS accent var defaults from index.css :root into the index.html inline script so they are always set synchronously before paint. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
3d7166740e
commit
988dc37b64
@ -9,18 +9,24 @@
|
||||
<meta name="mobile-web-app-capable" content="yes" />
|
||||
<title>UMBRA</title>
|
||||
<script>
|
||||
// Apply cached accent color before React hydrates to prevent cyan flash
|
||||
// Apply accent color before React hydrates to prevent FOUC.
|
||||
// Reads from localStorage cache; falls back to cyan on first visit.
|
||||
(function() {
|
||||
var s = document.documentElement.style;
|
||||
try {
|
||||
var c = localStorage.getItem('umbra-accent-color');
|
||||
if (c) {
|
||||
var p = JSON.parse(c);
|
||||
var s = document.documentElement.style;
|
||||
s.setProperty('--accent-h', p.h);
|
||||
s.setProperty('--accent-s', p.s);
|
||||
s.setProperty('--accent-l', p.l);
|
||||
return;
|
||||
}
|
||||
} catch(e) {}
|
||||
// First visit or corrupt cache — apply cyan defaults
|
||||
s.setProperty('--accent-h', '187');
|
||||
s.setProperty('--accent-s', '85.7%');
|
||||
s.setProperty('--accent-l', '53.3%');
|
||||
})();
|
||||
</script>
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
||||
|
||||
@ -15,10 +15,13 @@ const ACCENT_PRESETS: Record<string, { h: number; s: number; l: number }> = {
|
||||
export function useTheme() {
|
||||
const { settings } = useSettings();
|
||||
|
||||
// Ensure localStorage always has an accent color (even default cyan)
|
||||
// so the inline script in index.html can prevent flashes on every load
|
||||
// Only apply accent color once settings have loaded from the API.
|
||||
// The inline script in index.html handles the initial paint from localStorage cache.
|
||||
// Firing this effect with settings=undefined would overwrite the cache with cyan.
|
||||
useEffect(() => {
|
||||
const colorName = settings?.accent_color || 'cyan';
|
||||
if (!settings) return;
|
||||
|
||||
const colorName = settings.accent_color || 'cyan';
|
||||
const preset = ACCENT_PRESETS[colorName];
|
||||
if (!preset) return;
|
||||
|
||||
@ -31,7 +34,7 @@ export function useTheme() {
|
||||
try {
|
||||
localStorage.setItem('umbra-accent-color', JSON.stringify({ h, s, l }));
|
||||
} catch {}
|
||||
}, [settings?.accent_color]);
|
||||
}, [settings]);
|
||||
|
||||
return {
|
||||
accentColor: settings?.accent_color || 'cyan',
|
||||
|
||||
@ -26,10 +26,9 @@
|
||||
--ring: var(--accent-h) var(--accent-s) var(--accent-l);
|
||||
--radius: 0.5rem;
|
||||
|
||||
/* Default accent: cyan */
|
||||
--accent-h: 187;
|
||||
--accent-s: 85.7%;
|
||||
--accent-l: 53.3%;
|
||||
/* Accent vars are set by the inline script in index.html (from localStorage
|
||||
cache or cyan fallback). No CSS defaults here — they would race with the
|
||||
inline script and cause a flash of wrong color on refresh. */
|
||||
|
||||
/* Transitions */
|
||||
--transition-fast: 150ms;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user