Dynamically modify CSS variable at a context level #546
Replies: 2 comments
-
|
Thanks for the detailed write-up. The API you suggested makes sense and feels like a reasonable direction. We'll discuss this internally and think through what the right API and implementation could look like across platforms. Thanks again for bringing this up. |
Beta Was this translation helpful? Give feedback.
-
|
Sure. Couple of thoughts on this potential api and changes. Did some exploration of correct code (JS side). Apiimport { ScopedVariables } from 'uniwind'
<ScopedVariables variables={{ '--theme-color': '#3b82f6', '--gap': 8 }}>
<Text className="text-[--theme-color]">Blue text</Text>
<View className="gap-(--gap)" />
</ScopedVariables>Was thinking about hook or Changes// "packages/uniwind/src/core/context.ts"
export const UniwindContext = createContext({
scopedTheme: null as ThemeName | null,
variables: null as CSSVariables | null,
})on web we would need to have // `packages/uniwind/src/components/ScopedTheme/ScopedTheme.tsx`
export const ScopedTheme: React.FC<React.PropsWithChildren<ScopedThemeProps>> = ({ theme, children }) => {
const parent = useUniwindContext()
const value = useMemo<UniwindContextType>(
() => ({ scopedTheme: theme, variables: parent.variables }),
[theme, parent.variables],
)
return (
<UniwindContext.Provider value={value}>
<div className={theme} style={{ display: 'contents' }}>
{children}
</div>
</UniwindContext.Provider>
)
}// `packages/uniwind/src/components/ScopedVariables/ScopedVariables.tsx`
const contextValue = useMemo<UniwindContextType>(
() => ({ scopedTheme: parent.scopedTheme, variables: merged }),
[parent.scopedTheme, merged],
)
// this is from https://github.com/uni-stack/uniwind/blob/c8ed75fccb569dc7c37535a0a4762a112473c5f0/packages/uniwind/src/core/config/config.ts#L41
const inlineStyle = useMemo(() => {
const style: Record<string, string | number> = { display: 'contents' }
for (const [key, value] of Object.entries(variables)) {
style[key] = typeof value === 'number' ? `${value}px` : value
}
return style
}, [variables])
return (
<UniwindContext.Provider value={contextValue}>
<div style={inlineStyle as React.CSSProperties}>{children}</div>
</UniwindContext.Provider>
)
I'm not sure about ``${value}px Last part is about store & cache - probably just skip all together if var are set // `packages/uniwind/src/core/native/store.ts`
const hasContextVariables = uniwindContext.variables !== null
if (hasContextVariables) {
return this.resolveStyles(className, componentProps, state, uniwindContext)
}
const cacheKey = `${className}${state?.isDisabled ?? false}${state?.isFocused ?? false}${state?.isPressed ?? false}${isScopedTheme}
// rest is same.I've not looked too deep into native, it seems simpler. If you guys ok with above, I' probably prototype in a branch. |
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
-
Idea
It would be great to allow overrides of CSS variables at a React Context level, rather than at global scope. This would allow themes, or overrides, to apply to part of the app, rather than the whole global scope.
Why current solution does not work?
Looking at update-css-variables and its details, it seems to work
at the global level.
updateCSSVariablesapplies changes directly to the DOM usingdocument.documentElement.style.setProperty().updateCSSVariablesupdates the internal variable store with normalized values.This changes css var values at global level, not at element level. Therefor changes are applied to whole app, not part of it. From css perspective, we can set var value at any level as needed.
Prior Art
VariableContextProviderto manage design tokens like colors or spacing at runtime without rebuilding yourstylesheet. VariableContextProvider
varsis a function that takes a dictionary of CSS variables and returns a style object that can be used in ReactNative components. This allows you to set CSS variable values from JavaScript and have them flow down the component tree.
link
How would the API look?
Potentially could follow the
VariableContextProviderpattern.On web, this would probably mean setting the CSS var value on an injected
divor on its children.Beta Was this translation helpful? Give feedback.
All reactions