Skip to content

Component selectors no longer working with styled from @mui/material after upgrading to v6 #46102

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
koen-dev opened this issue May 7, 2025 · 1 comment · May be fixed by #46129
Open

Component selectors no longer working with styled from @mui/material after upgrading to v6 #46102

koen-dev opened this issue May 7, 2025 · 1 comment · May be fixed by #46129
Assignees
Labels
package: system Specific to @mui/system regression 🐛 A bug, but worse v6.x migration

Comments

@koen-dev
Copy link

koen-dev commented May 7, 2025

Steps to reproduce

Stackblitz:

I’m currently migrating from Material UI v5 to v6 and noticed that component selectors no longer work when using the styled utility from @mui/material.

Here’s a minimal reproduction of what used to work in v5:

import { styled } from '@mui/material';

const Child = styled('div')`
  color: red;
`;

const Parent = styled('div')`
  ${Child} {
    color: green;
  }
`;

export default function Example() {
  return (
    <Parent>
      <Child>Hello World</Child>
    </Parent>
  );
}

Current behavior

After upgrading to v6, Child remains red, the selector no longer applies.

Expected behavior

In v5, this correctly styled the Child green when inside Parent.

Context

If I switch the import to Emotion directly like this:

import styled from '@emotion/styled';

…the selector works again and Child becomes green as expected.

I’m using Emotion and have the SWC plugin installed. Is there something I’ve missed during the v6 migration? Do I need to add or change an importMap in the plugin config to support component selectors with MUI’s styled?

Appreciate any help or clarification, this used to work, and I’d like to stick with the MUI import for consistency and theme integration.

Your environment

npx @mui/envinfo

System:
OS: macOS 15.4.1
Binaries:
Node: 22.14.0 - /nix/store/2ribxb3gi87gj4331m6k0ydn0z90zfi7-nodejs-22.14.0/bin/node
npm: 10.9.2 - /nix/store/2ribxb3gi87gj4331m6k0ydn0z90zfi7-nodejs-22.14.0/bin/npm
pnpm: 9.12.1 - ~/Library/pnpm/pnpm
Browsers:
Chrome: 127.0.6533.120
Edge: 136.0.3240.50
Safari: 18.4
npmPackages:
@emotion/react: 11.14.0 => 11.14.0
@emotion/styled: 11.14.0 => 11.14.0
@mui/icons-material: 6.4.11 => 6.4.11
@mui/material: 6.4.11 => 6.4.11
@mui/system: 6.4.11 => 6.4.11
@mui/x-date-pickers: 7.29.2 => 7.29.2
@types/react: 18.3.20 => 18.3.20
react: 18.3.1 => 18.3.1
react-dom: 18.3.1 => 18.3.1
typescript: 5.8.3 => 5.8.3

Search keywords: component selector, emotion, plugin, v6

@koen-dev koen-dev added the status: waiting for maintainer These issues haven't been looked at yet by a maintainer label May 7, 2025
@zannager zannager added package: system Specific to @mui/system v6.x migration labels May 8, 2025
@siriwatknp siriwatknp moved this to In progress in Material UI public roadmap May 12, 2025
@siriwatknp siriwatknp added regression 🐛 A bug, but worse and removed status: waiting for maintainer These issues haven't been looked at yet by a maintainer labels May 12, 2025
@siriwatknp
Copy link
Member

siriwatknp commented May 12, 2025

Found the root cause, it's because of this line https://github.com/mui/material-ui/blob/master/packages/mui-system/src/createStyled/createStyled.js#L163

const transformStyle = (style) => {
      // On the server Emotion doesn't use React.forwardRef for creating components, so the created
      // component stays as a function. This condition makes sure that we do not interpolate functions
      // which are basically components used as a selectors.
      if (typeof style === 'function' && style.__emotion_real !== style) {
        return function styleFunctionProcessor(props) {
          return processStyle(props, style);
        };
      }
      if (isPlainObject(style)) { // <<<<<<<<<<<<<<<<<<<<<< the styled component matched this condition
        const serialized = preprocessStyles(style);
        if (!serialized.variants) {
          return serialized.style;
        }
        return function styleObjectProcessor(props) {
          return processStyle(props, serialized);
        };
      }
      return style;
    };

The component selector passed the isPlainObject because at runtime, React component is an object of { $$typeof: … }. The component selector should not be serialized, instead return it directly to let Emotion handle it.

The fix is simple, I will create a PR soon.

@siriwatknp siriwatknp linked a pull request May 12, 2025 that will close this issue
1 task
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
package: system Specific to @mui/system regression 🐛 A bug, but worse v6.x migration
Projects
Status: In progress
Development

Successfully merging a pull request may close this issue.

3 participants