A cleaner way to compose the sx prop (Material UI v5)
Published: 2021-12-25 13:03:13

Material UI v5 recently released their new design system [the Sx prop](https://mui.com/system/the-sx-prop/). The property includes style properties from CSS and @mui/system. Taking the MUI styling system to the next level. Personally I loved the new style engine from Material UI v5, enabling me to build Web Apps totally using the Material UI's ecosystem. Being used to the clean method of composing CSS classes using [classnames](https://www.npmjs.com/package/classnames) package, I found composing and conditionally chaing the `sx` props a bit unclean.

## The Feature
If you're totally new to mui v5, Let's first look at what exactly is sx props. `sx` prop is prop used in MuiV5 design system, that leverages mui shorthands and native css properties to provide a good styling experience. Below is a basic example of its usage.

```typescript
import { Box } from "@mui/material";

export default function App() {
  return (
    <Box className="App">
      <h1>mui-sx demo</h1>
      <Box
        // Passing Sx Prop Here
        sx={{
          mt: 2,
          width: 500,
          height: 500,
          background: "yellow",
          border: 1
        }}
      />
    </Box>
  );
}
```

{% codesandbox basic-sx-u23oj %}

As seen, sx prop is a JS object comprising of sx properties i.e mui short hands and native css props.

## The Problem
Being a JS object, using the sx prop across the markdown might look unclean. There might be usecases where you'd want to reuse some styling or apply conditionally styling.
Lets look at another example where in you need to conditionally color an element based on React state, also enforce modular styling pattern to ensure better reusability.
```typescript
import { Button } from "@mui/material";
import React from "react";
import { Box, Stack } from "@mui/material";

const sxBox = {
  width: "100%",
  height: 500
};
const sxBordered = {
  border: 1
};
const sxNight = {
  backgroundColor: "#000"
};
const sxDay = {
  backgroundColor: "yellow"
};

export default function App() {
  const [isDay, setDay] = React.useState(true);
  return (
    <>
      <Stack className="App" spacing={2}>
        <h1>mui-sx demo</h1>
        <div>Click toggle button below</div>
        <Box
          sx={
            // Follow are applied unconditionally
            {
              ...sxBox,
              ...sxBordered,
              ...(isDay && sxNight),
              ...(!isDay && sxDay)
            }

            // Follow sx applied when isDay === false
          }
        />
        <Button variant="contained" onClick={() => setDay(!isDay)}>
          Toggle
        </Button>
      </Stack>
    </>
  );
}

```
{% codesandbox mui-sx-ps-pokns %}

As seen in the sandbox, one might need lots of spread operators `(...)` and ternary conditions to implement composition of the sx prop. If you have worked on huge projects with modular css patterns, scaling above might get ugly.

## The Solution
This is where [mui-sx](https://www.npmjs.com/package/mui-sx) comes to rescue. Its a tiny JS library based off [classnames](https://www.npmjs.com/package/classnames), that helps elegantly compse the sx prop. Let's look at the above example written using `mui-sx`.

```typescript
import sx from "mui-sx";

import { Button } from "@mui/material";
import React from "react";
import { Box, Stack } from "@mui/material";

const sxBox = {
  width: "100%",
  height: 500
};
const sxBordered = {
  border: 1
};
const sxNight = {
  backgroundColor: "#000"
};
const sxDay = {
  backgroundColor: "yellow"
};

export default function App() {
  const [isDay, setDay] = React.useState(true);
  return (
    <>
      <Stack className="App" spacing={2}>
        <h1>mui-sx demo</h1>
        <div>Click to toggle color</div>
        <Box
          sx={sx(
            // Follow are applied unconditionally
            sxBox,
            sxBordered,
            // Follow sx applied when isDay === true
            {
              condition: isDay,
              sx: sxDay
            },
            // Follow sx applied when isDay === false
            {
              condition: !isDay,
              sx: sxNight
            }
          )}
        />
        <Button variant="contained" onClick={() => setDay(!isDay)}>
          Toggle
        </Button>
      </Stack>
    </>
  );
}
```

{% codesandbox sx-compose-example-z0mki %}


Much Cleaner! The syntax is very close to [classnames](https://www.npmjs.com/package/classnames) and if you are someone that has been using [classnames](https://www.npmjs.com/package/classnames) for a while then you might enjoy using [mui-sx](https://www.npmjs.com/package/mui-sx).


Link to the NPM Package: [mui-sx](https://www.npmjs.com/package/mui-sx)

---

**Hope that was helpful 😇**
If you have any questions/confusions/suggestions/corrections, Please do post down in the comments section below.


Rohan Salunke (https://okrohan.bio.link/)
{% user okrohan %}


---