material ui 'new' v5.0.0 injectFirst fails to set specificity
Asked Answered
C

2

10

MUI v5.0.0 was released today and in my spike branch I am attempting to update to the new version. I'm working through the steps in the mui-docs detailed here. I am using styled-components with NextJS and it seems that the mui-styles are not injecting first. I'm not sure what I can do differently to get ahead of this, afaik I've been following everything correctly in that guide and making changes incrementally. Yet, I'm still having the specificity bug.

styled-component's style below everything else.

enter image description here

<StylesProvider injectFirst> doesn't seem to work correctly now

Thoughts?

_app.tsx

import styled, { createGlobalStyle, ThemeProvider } from 'styled-components';
import withDarkMode, { useDarkMode } from 'next-dark-mode';
import defaultTheme from 'src/theme';
import TopNavigation from '@components/_molecules/TopNavigation/TopNavigation';
import StyledTypography from '@components/_atoms/Typography/StyledTypography';
import { Provider } from 'react-redux';
import { StylesProvider } from '@mui/styles';

function MyApp({ Component, pageProps }): JSX.Element {

  // ? https://nextjs.org/docs/basic-features/layouts
  const getLayout = Component.getLayout || (page => page);

  return (
    <StylesProvider injectFirst>
      <ThemeProvider theme={setTheme}>
        <RootStyles>
            <PageLayout>
              <TopNavigation />
              <Body>
                {getLayout(
                  <Provider store={store}>
                    <Component {...pageProps} />
                  </Provider>
                )}
              </Body>
              <Footer />
            </PageLayout>
        </RootStyles>
      </ThemeProvider>
    </StylesProvider>
  );
}

const RootStyles = styled.div`
  color: ${({ theme }) => theme.palette.font.primary};
`;

_document.js

import Document, { Html, Head, Main, NextScript } from 'next/document';
import { ServerStyleSheet } from 'styled-components';
import { ServerStyleSheets } from '@mui/styles';

class MyDocument extends Document {
  static async getInitialProps(ctx) {
    const styledComponentsSheet = new ServerStyleSheet();
    const materialSheets = new ServerStyleSheets();
    const originalRenderPage = ctx.renderPage;

    try {
      ctx.renderPage = () =>
        originalRenderPage({
          enhanceApp: App => props =>
            styledComponentsSheet.collectStyles(
              materialSheets.collect(<App {...props} />)
            ),
        });

      const initialProps = await Document.getInitialProps(ctx);

      return {
        ...initialProps,
        styles: (
          <>
            {initialProps.styles}
            {materialSheets.getStyleElement()}
            {styledComponentsSheet.getStyleElement()}
          </>
        ),
      };
    } finally {
      styledComponentsSheet.seal();
    }
  }

  // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
  render() {
    return (
      <Html lang="en" dir="ltr">
        <Head>
          <link rel="preconnect" href="https://fonts.gstatic.com" />
          <link
            rel="stylesheet"
            href="https://fonts.googleapis.com/css2?family=Poppins:wght@300;400;500;600&display=swap"
          />
          <link
            rel="stylesheet"
            href="https://cdnjs.cloudflare.com/ajax/libs/normalize/8.0.1/normalize.min.css"
          />
        </Head>
        <body>
          <Main />
          <NextScript />
        </body>
      </Html>
    );
  }
}

export default MyDocument;

package.json

...
 "dependencies": {
    "@emotion/react": "^11.4.1",
    "@emotion/styled": "^10.0.27",
    "@material-ui/core": "^4.12.1",
    "@mui/material": "^5.0.0",
    "@mui/styled-engine": "npm:@mui/styled-engine-sc@latest",
    "@mui/styles": "^5.0.0",
    "next": "10.2.3",
    "react": "17.0.2",
    "react-dom": "17.0.2",
    "storybook-addon-styled-component-theme": "^2.0.0",
    "styled-components": "^5.3.1",
  },
  "resolutions": {
    "@mui/styled-engine": "npm:@mui/styled-engine-sc@latest"
  },
...
Cyrille answered 17/9, 2021 at 4:18 Comment(1)
Hi! Did you manage to solve it?Rosiorosita
G
9

Try this

import StyledEngineProvider from '@mui/material/StyledEngineProvider';

function App() {
  return (
    <StyledEngineProvider injectFirst>
      <OtherComponents />
    </StyledEngineProvider>
  );
}
Gessner answered 17/10, 2021 at 14:30 Comment(5)
I'm using module CSS with a StyledEngineProvider component right now. It works perfectlyGessner
WORKED like a charm for me :)Opener
This did not work like a charm for meSemite
Saved my day ...i was importing from import { StyledEngineProvider } from "@mui/styled-engine-sc";Atheist
Do you wrap the component with StyledEngineProvider or the whole application ?Mandorla
E
0

I think that in your example it is working correctly, because the inject first is doing his job and injecting the CSS before yours. So all the classes have the same specificity (probably 0.1.0) and in that case, the order matters. So when you "inject first" the default CSS from MUI, then you can overwrite with your custom CSS in classes. I am using CCS Modules in Next 13. Here you have some docs about it. https://mui.com/material-ui/guides/interoperability/#css-modules

import { StyledEngineProvider } from "@mui/material/styles";

export default function YourComponent(){

return (
<StyledEngineProvider injectFirst>
 <OtherComponents/>
</StyledEngineProvider>
);
}

This worked for me. But, it only worked when I used it like this inside the particular component. I tried first creating a global provider wrapping all my app and it did not work. The problem I was having is that my custom styles written in css modules were overwritten by MUI defaults. Doing this helped change the order of the CSS and having the same specificity, the order is now correct. Hope this helps!

Elayneelazaro answered 27/10, 2023 at 16:9 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.