MCPcopy
hub / github.com/primer/react / ThemeProvider

Function ThemeProvider

packages/react/src/ThemeProvider.tsx:53–147  ·  view source on GitHub ↗
({children, ...props})

Source from the content-addressed store, hash-verified

51}
52
53export const ThemeProvider: React.FC<React.PropsWithChildren<ThemeProviderProps>> = ({children, ...props}) => {
54 // Get fallback values from parent ThemeProvider (if exists)
55 const {
56 theme: fallbackTheme,
57 colorMode: fallbackColorMode,
58 dayScheme: fallbackDayScheme,
59 nightScheme: fallbackNightScheme,
60 } = useTheme()
61
62 // Initialize state
63 const theme = props.theme ?? fallbackTheme ?? defaultTheme
64
65 const uniqueDataId = useId()
66 const {resolvedServerColorMode} = getServerHandoff(uniqueDataId)
67 const resolvedColorModePassthrough = React.useRef(resolvedServerColorMode)
68
69 const [colorMode, setColorMode] = React.useState(props.colorMode ?? fallbackColorMode ?? defaultColorMode)
70 const [dayScheme, setDayScheme] = React.useState(props.dayScheme ?? fallbackDayScheme ?? defaultDayScheme)
71 const [nightScheme, setNightScheme] = React.useState(props.nightScheme ?? fallbackNightScheme ?? defaultNightScheme)
72 const systemColorMode = useSystemColorMode()
73 const resolvedColorMode = resolvedColorModePassthrough.current || resolveColorMode(colorMode, systemColorMode)
74 const colorScheme = chooseColorScheme(resolvedColorMode, dayScheme, nightScheme)
75 const {resolvedTheme, resolvedColorScheme} = React.useMemo(
76 () => applyColorScheme(theme, colorScheme),
77 [theme, colorScheme],
78 )
79
80 // this effect will only run on client
81 React.useEffect(
82 function updateColorModeAfterServerPassthrough() {
83 const resolvedColorModeOnClient = resolveColorMode(colorMode, systemColorMode)
84
85 if (resolvedColorModePassthrough.current) {
86 // if the resolved color mode passed on from the server is not the resolved color mode on client, change it!
87 if (resolvedColorModePassthrough.current !== resolvedColorModeOnClient) {
88 window.setTimeout(() => {
89 // use ReactDOM.flushSync to prevent automatic batching of state updates since React 18
90 // ref: https://github.com/reactwg/react-18/discussions/21
91 ReactDOM.flushSync(() => {
92 // override colorMode to whatever is resolved on the client to get a re-render
93 setColorMode(resolvedColorModeOnClient)
94 })
95
96 // immediately after that, set the colorMode to what the user passed to respond to system color mode changes
97 setColorMode(colorMode)
98 })
99 }
100
101 resolvedColorModePassthrough.current = null
102 }
103 },
104 [colorMode, systemColorMode],
105 )
106
107 // Update state if props change
108 React.useEffect(() => {
109 setColorMode(props.colorMode ?? fallbackColorMode ?? defaultColorMode)
110 }, [props.colorMode, fallbackColorMode])

Callers

nothing calls this directly

Calls 7

useIdFunction · 0.90
useThemeFunction · 0.85
getServerHandoffFunction · 0.85
useSystemColorModeFunction · 0.85
resolveColorModeFunction · 0.85
chooseColorSchemeFunction · 0.85
applyColorSchemeFunction · 0.85

Tested by

no test coverage detected