Skip to content

Commit 7eb7b39

Browse files
Merge branch 'master' into sistent-table-docs
2 parents c0831e0 + b6192b0 commit 7eb7b39

File tree

17 files changed

+419
-85
lines changed

17 files changed

+419
-85
lines changed

onRenderBody.js

Lines changed: 62 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -5,53 +5,76 @@ import lighttheme, { darktheme } from "./src/theme/app/themeStyles";
55
const themes = { light: lighttheme, dark: darktheme };
66

77
const MagicScriptTag = (props) => {
8+
// FIX: Stringify the theme object outside the template literal to prevent syntax errors caused by unescaped quotes inside theme values.
9+
const themeJSON = JSON.stringify(props.theme);
10+
11+
// Injects CSS variables and theme state strictly before the first paint to prevent FOUC.
812
const codeToRunOnClient = `
913
(function() {
10-
// 1. Keeps SYSTEM as the priority preference
11-
const themeFromLocalStorage = localStorage.getItem('${DarkThemeKey}') || '${ThemeSetting.SYSTEM}';
14+
try {
15+
// 1. Keeps SYSTEM as the priority preference
16+
const themeFromLocalStorage = localStorage.getItem('${DarkThemeKey}') || '${ThemeSetting.SYSTEM}';
1217
13-
// 2. We change the check to look for LIGHT mode explicitly
14-
const systemLightModeSetting = () => window.matchMedia ? window.matchMedia('(prefers-color-scheme: light)') : null;
15-
16-
const isLightModeActive = () => {
17-
return !!systemLightModeSetting()?.matches;
18-
};
18+
// 2. We change the check to look for LIGHT mode explicitly
19+
const systemLightModeSetting = () => window.matchMedia ? window.matchMedia('(prefers-color-scheme: light)') : null;
20+
21+
const isLightModeActive = () => {
22+
return !!systemLightModeSetting()?.matches;
23+
};
1924
20-
let colorMode;
21-
switch (themeFromLocalStorage) {
22-
case '${ThemeSetting.SYSTEM}':
23-
// LOGIC CHANGE: If Light is active -> Light. Otherwise (Dark, No Preference, or Error) -> Dark.
24-
colorMode = isLightModeActive() ? '${ThemeSetting.LIGHT}' : '${ThemeSetting.DARK}'
25-
break
26-
case '${ThemeSetting.DARK}':
27-
case '${ThemeSetting.LIGHT}':
28-
colorMode = themeFromLocalStorage
29-
break
30-
default:
31-
// 3. Fallback to DARK in case of error
32-
colorMode = '${ThemeSetting.DARK}'
33-
}
25+
let colorMode;
26+
switch (themeFromLocalStorage) {
27+
case '${ThemeSetting.SYSTEM}':
28+
// LOGIC CHANGE: If Light is active -> Light. Otherwise (Dark, No Preference, or Error) -> Dark.
29+
colorMode = isLightModeActive() ? '${ThemeSetting.LIGHT}' : '${ThemeSetting.DARK}';
30+
break;
31+
case '${ThemeSetting.DARK}':
32+
case '${ThemeSetting.LIGHT}':
33+
colorMode = themeFromLocalStorage;
34+
break;
35+
default:
36+
// 3. Fallback to DARK in case of error
37+
colorMode = '${ThemeSetting.DARK}';
38+
}
3439
35-
const root = document.documentElement;
36-
const iterate = (obj) => {
37-
if (!obj) return;
38-
Object.keys(obj).forEach(key => {
39-
if (typeof obj[key] === 'object') {
40-
iterate(obj[key])
41-
} else {
42-
root.style.setProperty("--" + key, obj[key])
40+
const root = document.documentElement;
41+
const iterate = (obj) => {
42+
if (!obj) return;
43+
Object.keys(obj).forEach(key => {
44+
if (typeof obj[key] === 'object') {
45+
iterate(obj[key]);
46+
} else {
47+
root.style.setProperty("--" + key, obj[key]);
48+
}
49+
});
50+
};
51+
52+
// FIX: Inject the JSON object directly to avoid JSON.parse breaking on nested quotes.
53+
const parsedTheme = ${themeJSON};
54+
const theme = parsedTheme[colorMode];
55+
56+
if (theme) {
57+
iterate(theme);
4358
}
44-
})
59+
60+
root.style.setProperty('--initial-color-mode', colorMode);
61+
62+
// FIX: Setting data-theme is required for global CSS styles to apply correctly before React hydration.
63+
root.setAttribute('data-theme', colorMode);
64+
65+
// Sync the calculated theme globally so ThemeManager can pick it up seamlessly.
66+
window.__theme = colorMode;
67+
68+
} catch (e) {
69+
console.error('Dark mode injection failed:', e);
4570
}
46-
const parsedTheme = JSON.parse('${JSON.stringify(props.theme)}')
47-
const theme = parsedTheme[colorMode]
48-
iterate(theme)
49-
root.style.setProperty('--initial-color-mode', colorMode);
50-
})()
71+
})();
5172
`;
5273
return <script dangerouslySetInnerHTML={{ __html: codeToRunOnClient }} />;
5374
};
5475

55-
export const onRenderBody = ( { setPreBodyComponents }) => {
56-
setPreBodyComponents(<MagicScriptTag key="theme-injection" theme={themes} />);
57-
};
76+
// FIX: Using setHeadComponents instead of setPreBodyComponents ensures the script runs
77+
// strictly in the <head>, blocking the first paint until the theme is applied and completely eliminating FOUC.
78+
export const onRenderBody = ( { setHeadComponents }) => {
79+
setHeadComponents([<MagicScriptTag key="theme-injection" theme={themes} />]);
80+
};
Lines changed: 39 additions & 0 deletions
Loading
Lines changed: 37 additions & 0 deletions
Loading
Lines changed: 39 additions & 0 deletions
Loading

0 commit comments

Comments
 (0)