Search code examples
material-uibabeljsstyled-componentsviteemotion

How to refer to other Styled Components when using MUI styled function and Styled Components?


How should I refer to other Styled Components when using MUI styled function and Styled Components? This is the intended syntax:

const Parent = styled('div')({
  "&:hover": {
    [`${Child}`]: {
      color: 'red'
    }
  }
});

If I try to use the code above I get this error:

Component selectors can only be used in conjunction with @emotion/babel-plugin, the swc Emotion plugin, or another Emotion-aware compiler transform.

If I install the @emotion/babel-plugin and configure the plugin in the vite config file as suggested here I still get the same error.

(I also tried importing "@emotion/babel-plugin" without speciying options as in here or passing the options to the babel plugin and still failed)

This is my vite.config.ts:

export default defineConfig({
  plugins: [
    eslint(),
    react({
      babel: {
        plugins: [
          // "@emotion/babel-plugin"
          [
            "@emotion",
            // "@emotion/babel-plugin", <<< as an alternative also doesn't work
            {
              importMap: {
                "@mui/material/styles": {
                  styled: {
                    canonicalImport: ["@emotion/styled", "default"],
                    styledBaseImport: ["@mui/material/styles", "styled"]
                  }
                },
                "@mui/system": {
                  styled: {
                    canonicalImport: ["@emotion/styled", "default"],
                    styledBaseImport: ["@mui/system", "styled"]
                  }
                }
              }
            }
          ]
        ]
      },
      jsxImportSource: "@emotion/react"
    }),
    tsconfigPaths()
  ],
  resolve: {
    alias: {
      "@mui/styled-engine": "@mui/styled-engine-sc"
    }
  },
});

Should I switch from Styled Components to Emotion if I want to use this feature?


Solution

  • To answer your question:

    Should I switch from Styled Components to Emotion if I want to use this feature?

    If you do not need Emotion-specific features, importing styled from @mui/material/styles will help you avoid adding another package to your bundle and allow you to take advantage of the benefits for theming. Otherwise, Emotion will be fine.


    Some background

    I have tried using @emotion/styled, @mui/system/styled, @mui/material/styles, @mui/styled-engine, and @mui/styled-engine-sc with the template literal component selector syntax. None of them worked.

    However, component selector syntax worked for me when style objects were used with @emotion/styled and @mui/material/styles:

    const Parent = styled('div')( () => {
        return (
            {
                [`${Child}`]: {
                    border: '2px solid red',
                    backgroundColor: 'purple'
                }
            }
        );
    } );
    

    Using @mui/styled-engine-sc with component selector syntax within a style object rendered the Parent and Child components. But, @mui/styled-engine-sc did not respect some CSS cascading rules, and did not properly implement some of the styled API options.