Skip to content

Instantly share code, notes, and snippets.

@Hillsie
Last active October 16, 2021 06:06
Show Gist options
  • Save Hillsie/b8d65ac7767c95228bb0fe5221da7bd0 to your computer and use it in GitHub Desktop.
Save Hillsie/b8d65ac7767c95228bb0fe5221da7bd0 to your computer and use it in GitHub Desktop.
Notes Styling with material-ui v5 and Emotion

Styling with Material-ui V5.0 and Emotion as primary

Material UI

  1. Follow material-ui migration v4 to v5. May require manual upgrade with legacy refactor in future.
  2. As part of the package:
"@emotion/react": "^11.xxx",
"@emotion/styled": "^11.xxx",
"@mui/icons-material": "^5.0.1",
"@mui/lab": "^5.0.0-alpha.49",
"@mui/material": "^5.0.1",
"@mui/styles": "^5.0.1",

Prerequisites

  1. React Version 17.0.2 (This has New JSX transform. 17.0.0 does not AFAIK. Back ported to React 16.14.0, 15.7.0, and 0.14.10 versions)
  2. Installed devDependencies. Emotions Doco.
"@emotion/babel-plugin": "^11.3.0",
"@emotion/eslint-plugin": "^11.2.0",
  1. Added a .babelrc and included react emotions
{
  "presets": [
    [
      "@babel/preset-react",
      { "runtime": "automatic", "importSource": "@emotion/react" }
    ]
  ],
  "plugins": ["@emotion/babel-plugin"]
}
  1. In the component used the pragma. In my case, using the plain emotions pragma did not work. Used the this.
/* eslint-disable react/react-in-jsx-scope -- Unaware of jsxImportSource */
/** @jsxImportSource @emotion/react */

Not sure of the impact of this: /* eslint-disable react/react-in-jsx-scope -- Unaware of jsxImportSource */. Had no impact if removed. MUI Doco includes it.

  1. Using Emotion as the primary styling engine over MUI's version. https://mui.com/guides/interoperability/#emotion. Stack Overflow comments about the styling with MUI performance.

Styling Components

  1. Chose to use Emotion for styling over Material-ui 5.0 styled.
  2. Styled is a way to create React components that have styles attached to them. https://emotion.sh/docs/styled

Notes styling with Emotion

  1. Add the prop to the Mui component as a function
<Paper
    css={css({
            color:"#20b2aa",
            ":hover" :{
              color: "red",
            }
          })}
   elevation={2}
   sx={{ padding: "20px" }}
 >
          <div> Some text </div>
 
</Paper>
  1. Adding as template string and used CSS styling syntax.
<Paper
    css={css`
            color: #20b2aa;
            :hover {
              color: cyan;
            };
            background-color:red;
          `}
   elevation={2}
   sx={{ padding: "20px" }}
 >
          <div> Some text </div>
 
</Paper>
  1. Wrap a component with a MUI box component
function EmotionCSS() {
  return (
    <Box sx={{ width: 300 }}>
      <Slider defaultValue={30} />
      <Slider
        defaultValue={30}
        css={css`
          color: #20b2aa;

          :hover {
            color: #2e8b57;
          }
        `}
      />
    </Box>
    
    ...
    <EmotionCSS />
  1. Use the styled Emotion import. I saw something about performance. Need to lookup the scenario.
const Button = styled.button`
  color: turquoise;
`;

   <Button>This my button component.</Button>
        
  1. The button can be restyled using styled as a function.
const Fancy = styled(Button)`
  color: hotpink;
`;

<Fancy> another button </Fancy>
  1. Style Precedence. Styling as a const variable template string done as follows.
const danger = css`
  color: red;
`;

const base = css`
  background-color: darkgreen;
  color: turquoise;
`;

and then adding the CSS prop. Order of precedence is the last item wins in the array. Caveats with SSR.

   <RoomOutlinedIcon css={css([base, danger])} />

with mui theme useContext

  const roomIcon = (theme)=>css`
    color: ${theme.palette.common.blue};
    margin: 0 0.2rem 0 0;
  `;
Class names containing emotion styles from the className prop override css prop styles.
Class names from sources other than emotion are ignored and appended to the computed emotion class name.
  1. Component selectors
import styled from '@emotion/styled'
const Basic = ({ className }) => (
  <div className={className}>Some text</div>
)

const Fancy = styled(Basic)`
  color: hotpink;
`

render(<Fancy />)
  1. Object styles
import styled from '@emotion/styled'

const H1 = styled.h1(
  {
    fontSize: 20
  },
  props => ({ color: props.color })
)

render(<H1 color="lightgreen">This is lightgreen.</H1>)
  1. Template string with breakpoints and props
  const breakpoints = [0, 600, 960, 1280, 1920];
  const mq = breakpoints.map((bp) => `@media (min-width: ${bp}px)`);

const stepper_root = (theme) =>css`
  box-shadow: 0px 0px 3px rgba(0, 0, 0, 0.15);
  border-radius: 1px;
  padding: 0.7rem 0.7rem;
  max-width: 40rem;
  margin-left: 0rem;
  ${mq[0]} {
    border: 1px solid cyan;
    margin-left: 0rem;
    background-color:${theme.palette.common.blue};
  }
  ${mq[1]} {
    border: 1px solid green;
    margin-left: 1rem;
  background-color: white;
  }
  ${mq[2]} {
    border: 1px solid red;
    margin-left: 5rem;
  }
`;

Attributions

  1. https://www.ioannispoulakas.com/2020/10/16/using-the-new-jsx-transform-with-latest-react/#:~:text=Initially%20the%20new%20JSX%20transform,JSX%20transform%20to%20React%2016.14.
  2. https://emotion.sh/docs/@emotion/babel-plugin
  3. https://emotion.sh/docs/@emotion/eslint-plugin
  4. https://emotion.sh/docs/styled
  5. speed https://mui.com/system/basics/#performance-tradeoff
  6. https://stackoverflow.com/a/68675923/6207266
  7. StackOverflow
  8. Material-ui
  9. reactjs.org https://reactjs.org/blog/2020/09/22/introducing-the-new-jsx-transform.html
  10. https://emotion.sh/docs/styled#styling-any-component
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment