Skip to content

Commit 21df90e

Browse files
authored
Refactor ThemeManager for improved theme handling
Signed-off-by: Ankit Rewar <171806101+AnkitRewar11@users.noreply.github.com>
1 parent 7642946 commit 21df90e

File tree

1 file changed

+19
-0
lines changed

1 file changed

+19
-0
lines changed

src/theme/app/ThemeManager.js

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
// majority of code from https://www.joshwcomeau.com/react/dark-mode/ and https://github.com/gperl27/gatsby-styled-components-dark-mode
2+
// context provider for app to make accessible theme setting, toggle function, etc.
3+
14
import React, { createContext, useState, useEffect, useCallback } from "react";
25

36
export const ThemeSetting = {
@@ -18,6 +21,7 @@ const defaultState = {
1821

1922
export const ThemeManagerContext = createContext(defaultState);
2023

24+
// Safe check for browser environment
2125
const isBrowser = typeof window !== "undefined";
2226

2327
const systemDarkModeSetting = () =>
@@ -32,13 +36,16 @@ const applyThemeToDOM = (theme) => {
3236
const root = window.document.documentElement;
3337
root.style.setProperty("--initial-color-mode", theme);
3438
root.setAttribute("data-theme", theme);
39+
40+
// Sync with SSR injected state
3541
window.__theme = theme;
3642
};
3743

3844
export const ThemeManagerProvider = (props) => {
3945
const [themeSetting, setThemeSetting] = useState(ThemeSetting.SYSTEM);
4046
const [didLoad, setDidLoad] = useState(false);
4147

48+
// Initialize state from SSR script to prevent hydration mismatch
4249
const [isDark, setIsDark] = useState(() => {
4350
if (isBrowser) {
4451
if (window.__theme === ThemeSetting.DARK) return true;
@@ -52,8 +59,11 @@ export const ThemeManagerProvider = (props) => {
5259

5360
const root = window.document.documentElement;
5461
const initialColorValue = (root.style.getPropertyValue("--initial-color-mode") || "").trim();
62+
63+
// Prioritize SSR-injected theme
5564
const actualTheme = window.__theme || initialColorValue || ThemeSetting.LIGHT;
5665

66+
// Get stored theme from localStorage
5767
const storedTheme = localStorage.getItem(DarkThemeKey);
5868

5969
if (storedTheme && storedTheme !== ThemeSetting.SYSTEM) {
@@ -65,6 +75,7 @@ export const ThemeManagerProvider = (props) => {
6575
setIsDark(actualTheme === ThemeSetting.DARK);
6676
setThemeSetting(ThemeSetting.SYSTEM);
6777
} else {
78+
// Fallback to system preference
6879
const systemIsDark = isDarkModeActive();
6980
setIsDark(systemIsDark);
7081
const theme = systemIsDark ? ThemeSetting.DARK : ThemeSetting.LIGHT;
@@ -74,6 +85,7 @@ export const ThemeManagerProvider = (props) => {
7485
setDidLoad(true);
7586
}, []);
7687

88+
// Listen to system color scheme changes only when on SYSTEM mode
7789
useEffect(() => {
7890
if (!isBrowser || themeSetting !== ThemeSetting.SYSTEM) return;
7991

@@ -95,11 +107,14 @@ export const ThemeManagerProvider = (props) => {
95107
const newIsDark = !isDark;
96108
const newTheme = newIsDark ? ThemeSetting.DARK : ThemeSetting.LIGHT;
97109

110+
// Update state
98111
setIsDark(newIsDark);
99112
setThemeSetting(newTheme);
100113

114+
// Apply to DOM immediately
101115
applyThemeToDOM(newTheme);
102116

117+
// Persist to localStorage
103118
localStorage.setItem(DarkThemeKey, newTheme);
104119
}, [isDark]);
105120

@@ -128,10 +143,14 @@ export const ThemeManagerProvider = (props) => {
128143
return;
129144
}
130145

146+
// Update state
131147
setIsDark(newIsDark);
132148
setThemeSetting(setting);
133149

150+
// Apply to DOM immediately
134151
applyThemeToDOM(themeToApply);
152+
153+
// Persist to localStorage
135154
localStorage.setItem(DarkThemeKey, setting);
136155
},
137156
[isDark]

0 commit comments

Comments
 (0)