mui / material-ui

Material UI: Comprehensive React component library that implements Google's Material Design. Free forever.
https://mui.com/material-ui/
MIT License
93.43k stars 32.16k forks source link

CSS Vars Theme not applying correct styles when using nested/forced color schemes #43824

Open rossipedia opened 5 days ago

rossipedia commented 5 days ago

Steps to reproduce

Link to live example:

Steps: Use the toggle button group to switch between light and dark mode

Current behavior

The button labeled "LIGHT" switches its text color from black to white.

Expected behavior

The "LIGHT" button should not change its text color when switching themes.

Context

The docs say you should be able to force a specific color scheme by applying the configured selector to a parent element:

To force a specific color scheme for some part of your application, set the selector to the component or HTML element directly.

Your environment

Browser: Arc (Chromium)

image
npx @mui/envinfo ``` System: OS: macOS 15.0 Binaries: Node: 22.8.0 - ~/.local/state/fnm_multishells/34387_1726794020155/bin/node npm: 10.8.2 - ~/.local/state/fnm_multishells/34387_1726794020155/bin/npm pnpm: 9.6.0 - ~/.local/state/fnm_multishells/34387_1726794020155/bin/pnpm Browsers: Chrome: 128.0.6613.138 Edge: 129.0.2792.52 Safari: 18.0 npmPackages: @emotion/react: ^11.13.3 => 11.13.3 @emotion/styled: ^11.13.0 => 11.13.0 @mui/material: 6.1.1 => 6.1.1 @types/react: ^18.3.8 => 18.3.8 react: ^18.3.1 => 18.3.1 react-dom: ^18.3.1 => 18.3.1 typescript: ^5.6.2 => 5.6.2 ```

Search keywords: theme cssvars

aarongarciah commented 4 days ago

@siriwatknp without styleOverrides works as expected. The bug happens when defining raw colors: colors applied to the dark theme always win i.e. a component nested under a <div class="light"> still gets the colors from <html class="dark"> because the dark styles are found later in the cascade.

siriwatknp commented 4 days ago

@siriwatknp without styleOverrides works as expected. The bug happens when defining raw colors: colors applied to the dark theme always win i.e. a component nested under a <div class="light"> still gets the colors from <html class="dark"> because the dark styles are found later in the cascade.

I think that this more of a docs improvement rather than implementation bug. From the usage, it's correct that the color will change based on the theme.applyStyles('dark') due to how CSS work.

It'd be too complex to create a selector that prevent nesting like this.

aarongarciah commented 4 days ago

I agree the current behaviour is technically "correct", but it's also confusing since one would expect to be able to force a color scheme in certain parts of the DOM tree.

So users shouldn't expect to be able to force a color scheme when using raw color values, only when using tokens (CSS vars under the hood), correct?

siriwatknp commented 4 days ago

So users shouldn't expect to be able to force a color scheme when using raw color values, only when using tokens (CSS vars under the hood), correct?

Yes, that's totally corect.

rossipedia commented 3 days ago

So users shouldn't expect to be able to force a color scheme when using raw color values, only when using tokens (CSS vars under the hood), correct?

Yes that's totally correct.

If I'm understanding correctly, should this work if I use theme.vars.palette... in styleOverrides instead of theme.palette?

I haven't been able to get that to work either. Is there a method of component customization that will allow me to force a color scheme for a DOM sub-tree using CSS vars?