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.95k stars 32.27k forks source link

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

Open rossipedia opened 1 month ago

rossipedia commented 1 month 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 1 month 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 1 month 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 1 month 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 1 month 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 1 month 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?

trungutt commented 1 month ago

Any update on this issue?

AFAICT as long as theme.applyStyles('dark', {...}) comes after in theme definition, it wins over the selector from the sub DOM that we want to force light color scheme:

Screenshot 2024-09-30 at 12 59 21

I'm wondering if there's even a hacky colorSchemeSelector that could make this work.