feat(ui): helper de thème dark/light persisté (TDD)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,25 @@
|
|||||||
|
import { describe, it, expect, beforeEach } from "vitest";
|
||||||
|
import { nextTheme, getInitialTheme } from "./theme.js";
|
||||||
|
|
||||||
|
describe("nextTheme", () => {
|
||||||
|
it("bascule dark <-> light", () => {
|
||||||
|
expect(nextTheme("dark")).toBe("light");
|
||||||
|
expect(nextTheme("light")).toBe("dark");
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("getInitialTheme", () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
// @ts-expect-error - environnement node sans localStorage
|
||||||
|
delete globalThis.localStorage;
|
||||||
|
});
|
||||||
|
it("retombe sur dark sans localStorage", () => {
|
||||||
|
expect(getInitialTheme()).toBe("dark");
|
||||||
|
});
|
||||||
|
it("lit la valeur persistée si présente", () => {
|
||||||
|
const store: Record<string, string> = { "su-theme": "light" };
|
||||||
|
// @ts-expect-error - stub minimal
|
||||||
|
globalThis.localStorage = { getItem: (k: string) => store[k] ?? null };
|
||||||
|
expect(getInitialTheme()).toBe("light");
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
// client/src/lib/theme.ts
|
||||||
|
export type Theme = "dark" | "light";
|
||||||
|
const KEY = "su-theme";
|
||||||
|
|
||||||
|
export function nextTheme(t: Theme): Theme {
|
||||||
|
return t === "dark" ? "light" : "dark";
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getInitialTheme(): Theme {
|
||||||
|
try {
|
||||||
|
const v = globalThis.localStorage?.getItem(KEY);
|
||||||
|
return v === "light" ? "light" : "dark";
|
||||||
|
} catch {
|
||||||
|
return "dark";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function applyTheme(t: Theme): void {
|
||||||
|
try {
|
||||||
|
document.documentElement.dataset.theme = t;
|
||||||
|
globalThis.localStorage?.setItem(KEY, t);
|
||||||
|
} catch {
|
||||||
|
/* localStorage indisponible (mode privé) : on ignore la persistance */
|
||||||
|
}
|
||||||
|
}
|
||||||
+1
-1
@@ -3,7 +3,7 @@ import { defineConfig } from "vitest/config";
|
|||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
test: {
|
test: {
|
||||||
globals: true,
|
globals: true,
|
||||||
include: ["server/**/*.test.ts", "shared/**/*.test.ts"],
|
include: ["server/**/*.test.ts", "shared/**/*.test.ts", "client/**/*.test.ts"],
|
||||||
environment: "node",
|
environment: "node",
|
||||||
},
|
},
|
||||||
resolve: { alias: { "@shared": new URL("./shared", import.meta.url).pathname } },
|
resolve: { alias: { "@shared": new URL("./shared", import.meta.url).pathname } },
|
||||||
|
|||||||
Reference in New Issue
Block a user