mirror of
https://github.com/fabro-sh/fabro.git
synced 2026-09-20 00:11:34 +00:00
fix(fabro-web): default unsaved theme selection to dark
Remove the system color-scheme fallback from the web UI theme boot path. Fabro now uses a saved light/dark preference when present and otherwise starts in dark mode by default. Add a regression test for the shared theme selection helper and refresh the built web assets.
This commit is contained in:
parent
c4b51e44ea
commit
8e26d30460
9 changed files with 147 additions and 111 deletions
24
apps/fabro-web/app/lib/theme-selection.test.ts
Normal file
24
apps/fabro-web/app/lib/theme-selection.test.ts
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
import { describe, expect, test } from "bun:test";
|
||||
import { buildThemeBootScript, resolveTheme } from "./theme-selection";
|
||||
|
||||
describe("resolveTheme", () => {
|
||||
test("defaults to dark when no saved theme exists", () => {
|
||||
expect(resolveTheme(null)).toBe("dark");
|
||||
expect(resolveTheme("system")).toBe("dark");
|
||||
});
|
||||
|
||||
test("uses the saved theme when it is valid", () => {
|
||||
expect(resolveTheme("light")).toBe("light");
|
||||
expect(resolveTheme("dark")).toBe("dark");
|
||||
});
|
||||
});
|
||||
|
||||
describe("buildThemeBootScript", () => {
|
||||
test("defaults the boot script to dark without using system preference", () => {
|
||||
const script = buildThemeBootScript();
|
||||
|
||||
expect(script).toContain('localStorage.getItem("fabro-theme")');
|
||||
expect(script).toContain('t="dark"');
|
||||
expect(script).not.toContain("matchMedia");
|
||||
});
|
||||
});
|
||||
16
apps/fabro-web/app/lib/theme-selection.ts
Normal file
16
apps/fabro-web/app/lib/theme-selection.ts
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
type Theme = "light" | "dark";
|
||||
|
||||
const STORAGE_KEY = "fabro-theme";
|
||||
|
||||
function resolveTheme(storedTheme: string | null): Theme {
|
||||
return storedTheme === "light" || storedTheme === "dark"
|
||||
? storedTheme
|
||||
: "dark";
|
||||
}
|
||||
|
||||
function buildThemeBootScript(storageKey = STORAGE_KEY) {
|
||||
return `(function(){try{var t=localStorage.getItem("${storageKey}");if(t!=="light"&&t!=="dark")t="dark";document.documentElement.classList.add(t)}catch(e){document.documentElement.classList.add("dark")}})()`;
|
||||
}
|
||||
|
||||
export { STORAGE_KEY, buildThemeBootScript, resolveTheme };
|
||||
export type { Theme };
|
||||
|
|
@ -1,16 +1,10 @@
|
|||
import { createContext, useCallback, useContext, useEffect, useState } from "react";
|
||||
|
||||
type Theme = "light" | "dark";
|
||||
|
||||
const STORAGE_KEY = "fabro-theme";
|
||||
import { STORAGE_KEY, resolveTheme } from "./theme-selection";
|
||||
import type { Theme } from "./theme-selection";
|
||||
|
||||
function getInitialTheme(): Theme {
|
||||
if (typeof window === "undefined") return "dark";
|
||||
const stored = localStorage.getItem(STORAGE_KEY);
|
||||
if (stored === "light" || stored === "dark") return stored;
|
||||
return window.matchMedia("(prefers-color-scheme: dark)").matches
|
||||
? "dark"
|
||||
: "light";
|
||||
return resolveTheme(localStorage.getItem(STORAGE_KEY));
|
||||
}
|
||||
|
||||
function applyThemeClass(theme: Theme) {
|
||||
|
|
|
|||
|
|
@ -1,8 +1,9 @@
|
|||
import { isRouteErrorResponse, Outlet } from "react-router";
|
||||
import { ThemeProvider } from "./lib/theme";
|
||||
import { buildThemeBootScript } from "./lib/theme-selection";
|
||||
import "./app.css";
|
||||
|
||||
const themeScript = `(function(){try{var t=localStorage.getItem("fabro-theme");if(t!=="light"&&t!=="dark")t=window.matchMedia("(prefers-color-scheme:dark)").matches?"dark":"light";document.documentElement.classList.add(t)}catch(e){document.documentElement.classList.add("dark")}})()`;
|
||||
const themeScript = buildThemeBootScript();
|
||||
|
||||
export default function Root() {
|
||||
return (
|
||||
|
|
|
|||
2
apps/fabro-web/dist/assets/app.css
vendored
2
apps/fabro-web/dist/assets/app.css
vendored
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
6
apps/fabro-web/dist/index.html
vendored
6
apps/fabro-web/dist/index.html
vendored
|
|
@ -14,12 +14,12 @@
|
|||
href="https://fonts.googleapis.com/css2?family=Geist:wght@100..900&family=JetBrains+Mono:wght@400;500;600&display=swap"
|
||||
/>
|
||||
<script>
|
||||
(function(){try{var t=localStorage.getItem("fabro-theme");if(t!=="light"&&t!=="dark")t=window.matchMedia("(prefers-color-scheme:dark)").matches?"dark":"light";document.documentElement.classList.add(t)}catch(e){document.documentElement.classList.add("dark")}})()
|
||||
(function(){try{var t=localStorage.getItem("fabro-theme");if(t!=="light"&&t!=="dark")t="dark";document.documentElement.classList.add(t)}catch(e){document.documentElement.classList.add("dark")}})()
|
||||
</script>
|
||||
<link rel="stylesheet" href="/assets/app.css" />
|
||||
<link rel="stylesheet" href="/assets/entry-t2wvsf4c.css" />
|
||||
</head>
|
||||
<body class="h-full">
|
||||
<body class="h-full font-sans antialiased">
|
||||
<div id="root"></div>
|
||||
<script type="module" src="/assets/chunk-etxafnd6.js"></script>
|
||||
<script type="module" src="/assets/chunk-kv06br00.js"></script>
|
||||
|
|
@ -61,7 +61,7 @@
|
|||
<script type="module" src="/assets/chunk-sadshphz.js"></script>
|
||||
<script type="module" src="/assets/chunk-pmthkscp.js"></script>
|
||||
<script type="module" src="/assets/chunk-v61ks9f7.js"></script>
|
||||
<script type="module" src="/assets/entry-tfe07zw7.js"></script>
|
||||
<script type="module" src="/assets/entry-9ys2gakq.js"></script>
|
||||
<script type="module" src="/assets/chunk-n1k68xa8.js"></script>
|
||||
<script type="module" src="/assets/chunk-rsph5pvm.js"></script>
|
||||
<script type="module" src="/assets/chunk-9t57pdty.js"></script>
|
||||
|
|
|
|||
|
|
@ -14,11 +14,11 @@
|
|||
href="https://fonts.googleapis.com/css2?family=Geist:wght@100..900&family=JetBrains+Mono:wght@400;500;600&display=swap"
|
||||
/>
|
||||
<script>
|
||||
(function(){try{var t=localStorage.getItem("fabro-theme");if(t!=="light"&&t!=="dark")t=window.matchMedia("(prefers-color-scheme:dark)").matches?"dark":"light";document.documentElement.classList.add(t)}catch(e){document.documentElement.classList.add("dark")}})()
|
||||
(function(){try{var t=localStorage.getItem("fabro-theme");if(t!=="light"&&t!=="dark")t="dark";document.documentElement.classList.add(t)}catch(e){document.documentElement.classList.add("dark")}})()
|
||||
</script>
|
||||
{{styles}}
|
||||
</head>
|
||||
<body class="h-full">
|
||||
<body class="h-full font-sans antialiased">
|
||||
<div id="root"></div>
|
||||
{{scripts}}
|
||||
</body>
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue