Skip to content

Commit 3dbda57

Browse files
authored
manage dark/light theming with inline <script> to prevent flash (#643)
1 parent 0392e9c commit 3dbda57

File tree

1 file changed

+51
-33
lines changed

1 file changed

+51
-33
lines changed

src/entry-server.tsx

Lines changed: 51 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,43 +1,61 @@
11
import { createHandler, StartServer } from "@solidjs/start/server";
2-
import { ThemeProvider, useThemeContext } from "./data/theme-provider";
32

43
export default createHandler(() => (
54
<StartServer
65
document={({ assets, children, scripts }) => {
76
return (
8-
<ThemeProvider>
9-
{(() => {
10-
const ctx = useThemeContext();
7+
<html
8+
lang="en"
9+
>
10+
<head>
11+
<meta charset="utf-8" />
12+
<meta
13+
name="viewport"
14+
content="width=device-width, initial-scale=1"
15+
/>
16+
<link rel="icon" href="/favicon.ico" />
17+
<link
18+
rel="alternate icon"
19+
href="/favicon.svg"
20+
type="image/svg+xml"
21+
/>
22+
<script> {`
23+
function getCookie(name, cookieString) {
24+
if (!name || !cookieString) return "system";
25+
const match = cookieString.match(new RegExp(\`\\\\W?\${name}=(?<theme>\\\\w+)\`));
26+
return match?.groups?.theme || "system";
27+
}
1128
12-
return (
13-
<html
14-
lang="en"
15-
class={ctx.selectedTheme().value}
16-
data-theme={ctx.selectedTheme().theme}
17-
>
18-
<head>
19-
<meta charset="utf-8" />
20-
<meta
21-
name="viewport"
22-
content="width=device-width, initial-scale=1"
23-
/>
24-
<link rel="icon" href="/favicon.ico" />
25-
<link
26-
rel="alternate icon"
27-
href="/favicon.svg"
28-
type="image/svg+xml"
29-
/>
30-
<script src="/scripts/browser-specific.js" type="module" />
31-
{assets}
32-
</head>
33-
<body class="min-h-screen dark:bg-slate-900 bg-slate-50">
34-
<div id="app">{children}</div>
35-
{scripts}
36-
</body>
37-
</html>
38-
);
39-
})()}
40-
</ThemeProvider>
29+
const getUserTheme = () => getCookie("theme", document.cookie);
30+
31+
const getSystemTheme = () => window.matchMedia("(prefers-color-scheme: dark)").matches
32+
? {value: "dark", theme: "material-theme-ocean" }
33+
: {value: "light", theme: "min-light" };
34+
35+
const systemTheme = getSystemTheme();
36+
const themes = [
37+
{ value: "light", theme: "min-light" },
38+
{ value: "dark", theme: "material-theme-ocean" },
39+
{
40+
value: systemTheme.value,
41+
theme: systemTheme.theme,
42+
},
43+
];
44+
const themeName = getUserTheme();
45+
const theme = themes.find((t) => t.value == themeName) ?? themes[2];
46+
47+
document.documentElement.classList.add(theme.value);
48+
document.documentElement.setAttribute('data-theme', theme.theme);
49+
`}
50+
</script>
51+
<script src="/scripts/browser-specific.js" type="module" />
52+
{assets}
53+
</head>
54+
<body class="min-h-screen dark:bg-slate-900 bg-slate-50">
55+
<div id="app">{children}</div>
56+
{scripts}
57+
</body>
58+
</html>
4159
);
4260
}}
4361
/>

0 commit comments

Comments
 (0)