How combine styled-system with react material?

195 Views Asked by At

I wanna use styled-system in my project which is the admin panel. I built project basing on React Material and I have a lot of different forms with inputs, selects, checkboxes and so on. In many places I have to set some margins/paddings for elements and I make this moment with some custom Box component, that uses styled-system functions (space, color, etc). But it the end I got a rather cumbersome structure something like this :

<Box>
  <Box mb={10}>
    <Box mr={2}><TextField/></Box>
    <Box mr={2}><TextField/></Box>
    <Box mr={2}><TextField/></Box>
  </Box>
  
  <Box>
    <Box mr={2}><Select/></Box>
    <Box mr={2}><Select/></Box>
    <Box mr={2}><Select/></Box>
  </Box>
</Box>

And it's just a little part of the component. I think, in this situation it would be good to create some wrapper around TextField/Select components which will add styled-system functions to components. And then use them like :

<Box>
  <Box mb={10}>
    <TextField mr={2}/>
    <TextField mr={2}/>
    <TextField mr={2}/>
  </Box>
  
  <Box>
    <Select mr={2}/>
    <Select mr={2}/>
    <Select mr={2}/>
  </Box>
</Box>

But then I understand that react-material has a lot of components and what I have to do? Override all of them to have some similar style? Or what way can be more comfortable?

1

There are 1 best solutions below

0
On

So what you are asking for can definitely be achieved without adding that much noise to the markup.

First off, the styled markup works for all material-ui components. Luckily, styled-system is ALSO interoperable with styled-components. So you can do this

const StyledButton = styled(TextField)`
  color: red;
  // to access theme in a styled-system way
  ${get("mt", 3)};
`;

That accessor called get is a little unique, it comes from this package. It allows you to use all the styled-system flavoured keys inside of a styled-component.

If you wanted inline props for all the material components, like you described, its a little more involved. You would need to wrap each component with the proper decorators that enable such inline props. Creating basically a shadow library.

import styled from 'styled-components';
import { variant, space, layout, position } from 'styled-system';

export default styled(TextField)(
  position,
  layout,
  space,
  // whatever else
);

Check out the official build-a-box tutorial for better insight.