1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
|
import { useEffect, useMemo, useState, type ReactNode } from 'react'
import { Theme } from '@astryxdesign/core/theme'
import { defaultThemeSlug, themes } from '../astryx-themes'
import {
ThemeModeContext,
type ColorMode,
type ThemeModeValue,
} from './themeModeContext'
const STORAGE_KEY = 'astryx-starter-mode'
function getInitialMode(): ColorMode {
if (typeof window === 'undefined') return 'light'
try {
const stored = window.localStorage.getItem(STORAGE_KEY)
if (stored === 'light' || stored === 'dark') return stored
} catch {
// Storage can be unavailable in private browsing or embedded contexts.
}
return window.matchMedia('(prefers-color-scheme: dark)').matches
? 'dark'
: 'light'
}
export function ThemeModeProvider({ children }: { children: ReactNode }) {
const [mode, setMode] = useState<ColorMode>(getInitialMode)
useEffect(() => {
try {
window.localStorage.setItem(STORAGE_KEY, mode)
} catch {
// The theme still switches for this session if persistence is blocked.
}
}, [mode])
const value = useMemo<ThemeModeValue>(
() => ({
mode,
toggleMode: () => {
setMode((current) => (current === 'light' ? 'dark' : 'light'))
},
}),
[mode],
)
return (
<Theme theme={themes[defaultThemeSlug]} mode={mode}>
<ThemeModeContext.Provider value={value}>
{children}
</ThemeModeContext.Provider>
</Theme>
)
}
|