facebook / facebook/stylex

Theming not working as intended

Open
#1,606 1 comment 0 reactions 0 assignees View on GitHub
bug
Dominant language
JavaScript
Stars
10.3k
Forks
481
Avg merge
3d 8h
Merged PRs (30d)
13

Description

### Describe the issue

I have an issue where themes are not getting applied correctly and the CSS variables are reverting to the original variable value (not the correct themed version).

I have a CSS variable for UI scale. It is used in “spacing” tokens to scale their size up and down based on the overall UI scale. I created different themes to represent the preset UI scales.

```tsx
import { createTheme, defineVars } from "@stylexjs/stylex";

export const uiScale = defineVars({
"--ui-scale": "1",
});

const large = createTheme(uiScale, {
"--ui-scale": "1.1",
});
const small = createTheme(uiScale, {
"--ui-scale": "0.9",
});

export const uiScaleThemes = {
large,
small,
};

export type UIScaleThemes = keyof typeof uiScaleThemes;
```

Here’s an example of the spacing tokens:

```tsx
export const space = defineVars({
"--oat-space-1": `calc(4px * ${uiScale["--ui-scale"]})`,
});
```

This works ok with the initial value, but when I try to set any themes to change the value, it doesn’t work. The spacing variable stays at it’s original value.

Here’s an example of applying the themes - I just pass in the theme into the StyleX `props()` function. This component wraps the entire app:

```tsx
export function ThemeProviderR2({
theme: userTheme,
uiScale,
children,
}: React.PropsWithChildren) {
const { theme: storeTheme } = useThemeStore();
const theme = userTheme ?? storeTheme;
const uiScaleTheme =
uiScale && uiScale in uiScaleThemes ? uiScaleThemes[uiScale] : undefined;
const sx = props(theme == "dark" && darkTheme, uiScaleTheme);

return (


{children}

);
}
```

In my browser’s DevTools (tested both in Chrome and Firefox), I can see that the theme is applied correctly and overriding the variable. The new variable value is shown active, while the old variable is scratched out. And when I hover over the UI scale variable inside Firefox the `--oat-space-1` variable, I can see the overridden value. In Chrome I see it references the original value — but it still shows the original scratched out like Firefox.

Image

Image

But for some reason, the browser doesn’t render using the theme variable. It renders using the original variable. If I go into DevTools and change the value of the original - now scratched out UI space var, the component updates as expected.

I did a sanity check with a regular DOM element and inline styles with the same setup, and it worked fine. So it seems likely to be a specificity issue with StyleX.

```tsx



Target Text: Scale should be 5


```

I even tried throwing a `!important` on the override style in DevTools to see if it’s force it to take over, but that had no effect. Also tried using the `@property` definition to enforce it to update more (in case it was a cached computation) but that had no effect either.

Here’s an example of the generated CSS:

```css
@layer priority1 {
.x1ktcudu.x1ktcudu, .x1ktcudu.x1ktcudu:root {
--ui-scale: 2 !important;
}
}

/* The original style - has a "strikethrough" in DevTools */
@layer priority1 {
:root, .x1a594gj {
--ui-scale: 1;
}
}
```

and the DOM for reference:

```tsx



const greeting = 'Hello, World!';


```

### Expected behavior

Theme should apply and override correctly, and apply correctly to nested children. I shouldn't have to wrap each individual component with a theme override, it should respect/replicate platform behavior where parent CSS variable override is inherited.

### Steps to reproduce

I'm on StyleX version ^0.17.4 and React v19.
You can probably copy my code above to reproduce, but I can throw up a quick fork for reference if you need something to run and test.

### Test case

_No response_

### Additional comments

_No response_

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.