mui is no fun, but sx makes it bearable

On a webapp with mui (AKA Material UI), there’s everyone favorite component: <Box />. Why is Box beloved? It’s because unlike our usual goto div-soup generator, div lacks the sx prop. It’s sort of a mix between inline styles, inline “styled component” syntax, and maybe even a little bit of inline utility css. All in one. Box is boundless with potential.

<Box /> desugars into <div /> unless you give it a component="ul" prop, then it could become a <ul />. My assumption had been for a long time that without Box, I would not get the benefits of having sx props as an option. But you can! Using styled.

Here’s look at an example, we want to make vertical list using a ul. Even though it would be great if we could do this, this fails:

<br food={{}} />
<ul sx={(theme) => ({ /* 👈 in general, this would not work, you can't use the sx prop on an ordinary tagged element */
  listStyle: "none",
  display: "flex",
  flexDirection: "column",
  gap: theme.spacing(6),
})}>
    /* more elements */
</ul>

As an alternative that actually works, using @mui/system styled, we can give a name to these styles and preserve the sx prop capability allowing us to have adhoc styles when we need them still.

export const VerticallySpacedList = styled(`ul`)(({ theme }) => ({
  listStyle: "none",
  display: "flex",
  flexDirection: "column",
  gap: theme.spacing(6),
}));

Now, we can reference this as we’d like:

<VerticallySpacedList>
    /* more elements */
</VerticallySpacedList>

What’s nice about this is that we can use sx on <VerticallySpacedList />:

<VerticallySpacedList sx={{fontSize: "2rem", lineHeight: 1.5}}>
    /* more elements */
</VerticallySpacedList>

This saves us from have an explosion of one-off subtly named components like VerticallySpacedList and VerticallySpacedListWithBiggerTextSize and BoldVerticallySpacedList. There’s a core, common style as a base and then sx handles incidentials.

There’s nothing quite like Tailwind for utility css, but with <Box />, sx and styled, maybe it comes in a distant second.

Follow me on Mastodon @ryanmr@mastodon.cloud.

Follow me on Twitter @ryanmr.