DEV Community πŸ‘©β€πŸ’»πŸ‘¨β€πŸ’»

Cover image for A cleaner way to compose the sx prop (Material UI v5)
Rohan Salunke
Rohan Salunke

Posted on • Updated on

A cleaner way to compose the sx prop (Material UI v5)

Material UI v5 recently released their new design 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 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.

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>
  );
}
Enter fullscreen mode Exit fullscreen mode

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.

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>
    </>
  );
}

Enter fullscreen mode Exit fullscreen mode

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 comes to rescue. Its a tiny JS library based off classnames, that helps elegantly compse the sx prop. Let's look at the above example written using mui-sx.

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>
    </>
  );
}
Enter fullscreen mode Exit fullscreen mode

Much Cleaner! The syntax is very close to classnames and if you are someone that has been using classnames for a while then you might enjoy using mui-sx.

Link to the NPM 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/)

okrohan image

Top comments (4)

Collapse
 
hirokitakahashi profile image
Hiroki Takahashi

This article was quite informative.

However, IMHO, it's probably better NOT to use sx when styling a component conditionally (even if "mui-sx" allows you to do so smoothly).
According to MUI's documentation...

When to use MUI System
The sx prop is best suited for applying one-off styles to custom components.

If a component's style needs to change conditionally, I'd opt for the styled-components API

Collapse
 
maniator profile image
Naftali Lubin

You can already pass arrays to the sx prop -- what does this add?

Collapse
 
artidata profile image
Imaduddin Haetami

My preference for reuse styling is themeing. sx props for one call thing, when theming not possible.

Collapse
 
okrohan profile image
Rohan Salunke

Yep! That's the way to go with mui.

Welcome! πŸ‘‹ New to DEV? Head over to our Welcome Thread and tell us what you're working on!