1- //majority of code from https://www.joshwcomeau.com/react/dark-mode/ and https://github.com/gperl27/gatsby-styled-components-dark-mode
2-
3- //context provider for app to make accessible theme setting, toggle function, etc.
4-
51import React , { createContext , useState , useEffect , useCallback } from "react" ;
62
73export const ThemeSetting = {
@@ -22,11 +18,11 @@ const defaultState = {
2218
2319export const ThemeManagerContext = createContext ( defaultState ) ;
2420
25- // Safe check for browser environment
2621const isBrowser = typeof window !== "undefined" ;
2722
2823const systemDarkModeSetting = ( ) =>
2924 isBrowser && window . matchMedia ? window . matchMedia ( "(prefers-color-scheme: dark)" ) : null ;
25+
3026const isDarkModeActive = ( ) => {
3127 return ! ! systemDarkModeSetting ( ) ?. matches ;
3228} ;
@@ -36,32 +32,39 @@ const applyThemeToDOM = (theme) => {
3632 const root = window . document . documentElement ;
3733 root . style . setProperty ( "--initial-color-mode" , theme ) ;
3834 root . setAttribute ( "data-theme" , theme ) ;
35+ window . __theme = theme ;
3936} ;
4037
4138export const ThemeManagerProvider = ( props ) => {
4239 const [ themeSetting , setThemeSetting ] = useState ( ThemeSetting . SYSTEM ) ;
4340 const [ didLoad , setDidLoad ] = useState ( false ) ;
44- const [ isDark , setIsDark ] = useState ( false ) ;
41+
42+ const [ isDark , setIsDark ] = useState ( ( ) => {
43+ if ( isBrowser ) {
44+ if ( window . __theme === ThemeSetting . DARK ) return true ;
45+ if ( window . __theme === ThemeSetting . LIGHT ) return false ;
46+ }
47+ return false ;
48+ } ) ;
4549
4650 useEffect ( ( ) => {
4751 if ( ! isBrowser ) return ;
4852
4953 const root = window . document . documentElement ;
50- const initialColorValue = root . style . getPropertyValue ( "--initial-color-mode" ) ;
54+ const initialColorValue = ( root . style . getPropertyValue ( "--initial-color-mode" ) || "" ) . trim ( ) ;
55+ const actualTheme = window . __theme || initialColorValue || ThemeSetting . LIGHT ;
5156
52- // Get stored theme from localStorage
5357 const storedTheme = localStorage . getItem ( DarkThemeKey ) ;
5458
5559 if ( storedTheme && storedTheme !== ThemeSetting . SYSTEM ) {
5660 const isDarkTheme = storedTheme === ThemeSetting . DARK ;
5761 setIsDark ( isDarkTheme ) ;
5862 setThemeSetting ( storedTheme ) ;
5963 applyThemeToDOM ( storedTheme ) ;
60- } else if ( initialColorValue ) {
61- setIsDark ( initialColorValue === ThemeSetting . DARK ) ;
64+ } else if ( actualTheme ) {
65+ setIsDark ( actualTheme === ThemeSetting . DARK ) ;
6266 setThemeSetting ( ThemeSetting . SYSTEM ) ;
6367 } else {
64- // Fallback to system preference
6568 const systemIsDark = isDarkModeActive ( ) ;
6669 setIsDark ( systemIsDark ) ;
6770 const theme = systemIsDark ? ThemeSetting . DARK : ThemeSetting . LIGHT ;
@@ -71,7 +74,6 @@ export const ThemeManagerProvider = (props) => {
7174 setDidLoad ( true ) ;
7275 } , [ ] ) ;
7376
74- // Listen to system color scheme changes only when on SYSTEM mode
7577 useEffect ( ( ) => {
7678 if ( ! isBrowser || themeSetting !== ThemeSetting . SYSTEM ) return ;
7779
@@ -93,14 +95,11 @@ export const ThemeManagerProvider = (props) => {
9395 const newIsDark = ! isDark ;
9496 const newTheme = newIsDark ? ThemeSetting . DARK : ThemeSetting . LIGHT ;
9597
96- // Update state
9798 setIsDark ( newIsDark ) ;
9899 setThemeSetting ( newTheme ) ;
99100
100- // Apply to DOM immediately
101101 applyThemeToDOM ( newTheme ) ;
102102
103- // Persist to localStorage
104103 localStorage . setItem ( DarkThemeKey , newTheme ) ;
105104 } , [ isDark ] ) ;
106105
@@ -129,14 +128,10 @@ export const ThemeManagerProvider = (props) => {
129128 return ;
130129 }
131130
132- // Update state
133131 setIsDark ( newIsDark ) ;
134132 setThemeSetting ( setting ) ;
135133
136- // Apply to DOM immediately
137134 applyThemeToDOM ( themeToApply ) ;
138-
139- // Persist to localStorage
140135 localStorage . setItem ( DarkThemeKey , setting ) ;
141136 } ,
142137 [ isDark ]
0 commit comments