Skip to content

Commit 763f690

Browse files
committed
chore(architecture): remove the need for a Context to store color mode
1 parent fc5af96 commit 763f690

4 files changed

Lines changed: 48 additions & 133 deletions

File tree

apps/vivsha.ws/app/_components/ColorModeContext.tsx

Lines changed: 0 additions & 89 deletions
This file was deleted.

apps/vivsha.ws/app/_components/GlobalProviders.tsx

Lines changed: 0 additions & 30 deletions
This file was deleted.

apps/vivsha.ws/app/_components/ThemeSwitcher.tsx

Lines changed: 47 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,10 @@
22

33
import { faDesktop, faMoon, faSun } from "@fortawesome/free-solid-svg-icons"
44
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"
5+
import { DARK_COLOR_MODE_CLASS, LIGHT_COLOR_MODE_CLASS } from "@vivshaw/basalt"
56
import { useEffect, useState } from "react"
67

7-
import { ColorMode, useColorMode } from "./ColorModeContext"
8+
import { COLOR_MODE_STORAGE_KEY } from "#data"
89
import {
910
button,
1011
buttonActive,
@@ -15,6 +16,8 @@ import {
1516
indicatorSystem,
1617
} from "./ThemeSwitcher.css"
1718

19+
type ColorMode = "light" | "dark" | "system"
20+
1821
const themes: { key: ColorMode; icon: typeof faDesktop; label: string }[] = [
1922
{ key: "system", icon: faDesktop, label: "System theme" },
2023
{ key: "light", icon: faSun, label: "Light theme" },
@@ -27,16 +30,50 @@ const indicatorPositions: Record<ColorMode, string> = {
2730
dark: indicatorDark,
2831
}
2932

30-
export function ThemeSwitcher() {
31-
const { colorMode, setColorMode } = useColorMode()
32-
const [mounted, setMounted] = useState(false)
33+
/**
34+
* reads the user's color mode preference from localStorage.
35+
*/
36+
function getStoredColorMode(): ColorMode {
37+
try {
38+
const stored = localStorage.getItem(COLOR_MODE_STORAGE_KEY)
39+
if (stored === "light" || stored === "dark" || stored === "system") {
40+
return stored
41+
}
42+
} catch {
43+
// localStorage unavailable
44+
}
45+
return "system"
46+
}
47+
48+
/**
49+
* applies a color mode by updating DOM classes and persisting to localStorage.
50+
*/
51+
function applyStoredColorMode(mode: ColorMode) {
52+
document.documentElement.classList.remove(
53+
DARK_COLOR_MODE_CLASS,
54+
LIGHT_COLOR_MODE_CLASS,
55+
)
3356

34-
useEffect(() => {
35-
setMounted(true)
36-
}, [])
57+
if (mode === "dark") {
58+
document.documentElement.classList.add(DARK_COLOR_MODE_CLASS)
59+
} else if (mode === "light") {
60+
document.documentElement.classList.add(LIGHT_COLOR_MODE_CLASS)
61+
}
62+
// "system" means no explicit class - CSS handles via prefers-color-scheme
63+
64+
try {
65+
localStorage.setItem(COLOR_MODE_STORAGE_KEY, mode)
66+
} catch {
67+
// localStorage unavailable
68+
}
69+
}
70+
71+
export function ThemeSwitcher() {
72+
const [colorMode, setColorMode] = useState<ColorMode>(getStoredColorMode())
3773

38-
if (!mounted) {
39-
return null
74+
function handleSetColorMode(mode: ColorMode) {
75+
setColorMode(mode)
76+
applyStoredColorMode(mode)
4077
}
4178

4279
return (
@@ -49,7 +86,7 @@ export function ThemeSwitcher() {
4986
aria-label={label}
5087
aria-pressed={colorMode === key}
5188
className={`${button} ${colorMode === key ? buttonActive : ""}`}
52-
onClick={() => setColorMode(key)}
89+
onClick={() => handleSetColorMode(key)}
5390
>
5491
<FontAwesomeIcon icon={icon} size="sm" />
5592
</button>

apps/vivsha.ws/app/layout.tsx

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ import {
88

99
import { author, COLOR_MODE_STORAGE_KEY, site } from "#data"
1010
import { metadataHelper } from "#lib/metadataHelpers"
11-
import { GlobalProviders } from "./_components/GlobalProviders"
1211

1312
export const viewport: Viewport = {
1413
colorScheme: "dark light",
@@ -92,9 +91,7 @@ export default function RootLayout({
9291
<script>{JS_DETECTION_SNIPPET}</script>
9392
<script>{COLOR_MODE_SNIPPET}</script>
9493
</head>
95-
<body>
96-
<GlobalProviders>{children}</GlobalProviders>
97-
</body>
94+
<body>{children}</body>
9895
</html>
9996
)
10097
}

0 commit comments

Comments
 (0)