//

React Component Library with Material UI

Using Material UI which supports Styled Components is an excellent combination of libraries to start building a design system of your own

Why Material UI?

Creating a custom component library from scratch can be tedious and time-consuming. Instead, it’s much faster to use one of an existing component libraries well-architected components than to spin up a custom one. Instead of using Sass or JS in CSS, I prefer using Styled Components for the ability to pass functions and props, write regular CSS, inject custom properties like any other React component and just the overall component-driven nature of it. Well, the good news is, Material UI pretty much supports it out of the box.

Setting up Material UI

Install Material-UI's source files via npm:

npm install @material-ui/core

Or using yarn:

yarn add @material-ui/core

Material-UI components work without any additional setup, and also don't pollute the global scope.

import styled from "styled-components";
import Button from "@material-ui/core/Button";

const StyledButton = styled(Button)`
  color: white;
  && :hover {
    color: blue;
  }
`;

Pretty simple isn't it?

Specificity and using &&

We just have to use && to make our selector specific enough. Because both Styled Components and Material UI inject styles at the bottom of the head tag.

Using ThemeProvider for avoiding use of && everywhere

If we want to be able to style our Material UI components without using && then we have to do the following:

import { StylesProvider } from '@material-ui/styles';
import Button from "@material-ui/core/Button";

<StylesProvider injectFirst>
  <Button>Hey there!</Button>
</StylesProvider>

All it does is ensure that Material UI’s styles get injected first so that Styled Components classes take priority.

Overriding Specific Material UI Classes

We still want to be able to override specific classes in our Material UI components. For example, we may want to style our button label different from the default. Here is how you would do that:

import React from 'react';
import styled from 'styled-components';
import { StylesProvider } from '@material-ui/styles';
import Button from "@material-ui/core/Button";

const CustomButton = styled(({...rest}) => (
  <Button classes={{label: 'label'}} {...rest}/>
))`
  .label {
    color: blue;
  }  
`

<StylesProvider injectFirst>
  <CustomButton>Blue Button</CustomButton>
</StylesProvider>

All we are doing is returning a button component with the label class renamed as ‘label’ instead of the Material UI class name .MuiButton-label . We spread the rest of the properties so that we can pass our MUI props as usual.

Passing props only to Styled Components

If we want to pass props to Styled Components and we don’t want our MUI components to receive them, we can do that like so:

import React from 'react';
import styled from 'styled-components';
import { StylesProvider } from '@material-ui/styles';
import Button from "@material-ui/core/Button";

const CustomButton = styled(({styledComponentProp, ...rest}) => (
  <Button classes={{label: 'label'}} {...rest}/>
))`
  .label {
    color: blue;
    font-size: ${props => props.styledComponentProp};
  }  
`

<StylesProvider injectFirst>
  <CustomButton styledComponentProp="20">Blue Button</CustomButton>
</StylesProvider>

Leverage Material UI Theme

Material UI has a very thorough theme based on Material Design principles. If you’re using the component library, chances are you aren’t trying to build a theme from scratch either. We can leverage the Material UI theme quite easily. We just pass in the theme to our Styled Components ThemeProvider:

import React from 'react';
import styled, { ThemeProvider } from 'styled-components';
import { createMuiTheme} from '@material-ui/core/styles';
import Button from '@material-ui/core/Button';

const theme = createMuiTheme();

const StyledButton = styled(Button)`
  color: ${props => props.theme.palette.primary.main};
`;

export default () => (
    <ThemeProvider theme={theme}>
        <StyledButton>Styled Components</StyledButton>
    </ThemeProvider>
)

Conclusion

The Material UI docs have more detailed information, but hopefully, this gave a much quicker overview on how you would use these techniques to leverage both libraries, and why.