Skip to content

Commit ce6c0f4

Browse files
matthprostlisalupi
authored andcommitted
fix: theme provider to inject theme in head (#5435)
1 parent a0061e0 commit ce6c0f4

File tree

2 files changed

+35
-7
lines changed

2 files changed

+35
-7
lines changed

.changeset/neat-regions-repair.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@ultraviolet/ui": patch
3+
---
4+
5+
Fix `<ThemeProvider />` to inject theme variable in the `<head>` of the page

packages/ui/src/theme/ThemeProvider.tsx

Lines changed: 30 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
import { consoleLightTheme, theme as themeContract } from '@ultraviolet/themes'
44
import { assignInlineVars } from '@vanilla-extract/dynamic'
55
import type { ReactNode } from 'react'
6-
import { createContext, useContext } from 'react'
6+
import { createContext, useContext, useEffect } from 'react'
77

88
const ThemeContext = createContext(consoleLightTheme)
99

@@ -31,14 +31,37 @@ type ThemeProviderProps = {
3131
}
3232

3333
/**
34-
* ThemeProvider will apply generated global CSS variables to the application.
34+
* ThemeProvider will apply generated global CSS variables to the application in the `<head>`.
3535
* If no theme is provided, it will default to `lightTheme`.
3636
*/
3737
export const ThemeProvider = ({
3838
children,
3939
theme = consoleLightTheme,
40-
}: ThemeProviderProps) => (
41-
<ThemeContext.Provider value={theme}>
42-
<div style={assignInlineVars(themeContract, theme)}>{children}</div>
43-
</ThemeContext.Provider>
44-
)
40+
}: ThemeProviderProps) => {
41+
useEffect(() => {
42+
const styleId = 'uv-theme'
43+
const existingStyle = document.getElementById(styleId)
44+
const cssVars = assignInlineVars(themeContract, theme)
45+
const cssString = `:root { ${Object.entries(cssVars)
46+
.map(([key, value]) => `${key}: ${value};`)
47+
.join(' ')} }`
48+
49+
if (existingStyle) {
50+
existingStyle.textContent = cssString
51+
} else {
52+
const style = document.createElement('style')
53+
style.id = styleId
54+
style.textContent = cssString
55+
document.head.appendChild(style)
56+
}
57+
58+
return () => {
59+
const style = document.getElementById(styleId)
60+
if (style) {
61+
style.remove()
62+
}
63+
}
64+
}, [theme])
65+
66+
return <ThemeContext.Provider value={theme}>{children}</ThemeContext.Provider>
67+
}

0 commit comments

Comments
 (0)