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" />
|
<meta name="mobile-web-app-capable" content="yes" />
|
||||||
<title>UMBRA</title>
|
<title>UMBRA</title>
|
||||||
<script>
|
<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() {
|
(function() {
|
||||||
|
var s = document.documentElement.style;
|
||||||
try {
|
try {
|
||||||
var c = localStorage.getItem('umbra-accent-color');
|
var c = localStorage.getItem('umbra-accent-color');
|
||||||
if (c) {
|
if (c) {
|
||||||
var p = JSON.parse(c);
|
var p = JSON.parse(c);
|
||||||
var s = document.documentElement.style;
|
|
||||||
s.setProperty('--accent-h', p.h);
|
s.setProperty('--accent-h', p.h);
|
||||||
s.setProperty('--accent-s', p.s);
|
s.setProperty('--accent-s', p.s);
|
||||||
s.setProperty('--accent-l', p.l);
|
s.setProperty('--accent-l', p.l);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
} catch(e) {}
|
} 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>
|
</script>
|
||||||
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
<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() {
|
export function useTheme() {
|
||||||
const { settings } = useSettings();
|
const { settings } = useSettings();
|
||||||
|
|
||||||
// Ensure localStorage always has an accent color (even default cyan)
|
// Only apply accent color once settings have loaded from the API.
|
||||||
// so the inline script in index.html can prevent flashes on every load
|
// 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(() => {
|
useEffect(() => {
|
||||||
const colorName = settings?.accent_color || 'cyan';
|
if (!settings) return;
|
||||||
|
|
||||||
|
const colorName = settings.accent_color || 'cyan';
|
||||||
const preset = ACCENT_PRESETS[colorName];
|
const preset = ACCENT_PRESETS[colorName];
|
||||||
if (!preset) return;
|
if (!preset) return;
|
||||||
|
|
||||||
@ -31,7 +34,7 @@ export function useTheme() {
|
|||||||
try {
|
try {
|
||||||
localStorage.setItem('umbra-accent-color', JSON.stringify({ h, s, l }));
|
localStorage.setItem('umbra-accent-color', JSON.stringify({ h, s, l }));
|
||||||
} catch {}
|
} catch {}
|
||||||
}, [settings?.accent_color]);
|
}, [settings]);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
accentColor: settings?.accent_color || 'cyan',
|
accentColor: settings?.accent_color || 'cyan',
|
||||||
|
|||||||
@ -26,10 +26,9 @@
|
|||||||
--ring: var(--accent-h) var(--accent-s) var(--accent-l);
|
--ring: var(--accent-h) var(--accent-s) var(--accent-l);
|
||||||
--radius: 0.5rem;
|
--radius: 0.5rem;
|
||||||
|
|
||||||
/* Default accent: cyan */
|
/* Accent vars are set by the inline script in index.html (from localStorage
|
||||||
--accent-h: 187;
|
cache or cyan fallback). No CSS defaults here — they would race with the
|
||||||
--accent-s: 85.7%;
|
inline script and cause a flash of wrong color on refresh. */
|
||||||
--accent-l: 53.3%;
|
|
||||||
|
|
||||||
/* Transitions */
|
/* Transitions */
|
||||||
--transition-fast: 150ms;
|
--transition-fast: 150ms;
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user