Migrating from Rebass to Wallop System

April 10, 2020

Last year I talked at JAMstack meetup in London. As part of this talk, I created an online guide to help people get started with JAMstack, it's called jamstack.wtf.

I built it with Rebass. If you're not familiar with Rebass, it's a React UI Library. It's one of many projects by Brent Jackson, and it's powered by Styled System.

At the time it was the right tool for the job. But the times are a changing! I now have Wallop System, which is my own design system.

It's time to migrate from Rebass to Wallop System.


Wallop System was created, developed and deployed with Modulz. Design systems generated by Modulz have a similar API to Styled System and Theme UI, but with a few differences.

The migration from Rebass to Wallop would be the same for any Modulz generated design system

Props

The first class support of system props in Rebass and Wallop System are different. With Rebass, you can use the following props on all components:

  • margin, marginTop, mt, marginRight, mr, marginBottom, mb, marginLeft, ml, marginX, mx, marginY, my
  • padding, paddingTop, pt, paddingRight, pr, paddingBottom, pb, paddingLeft, pl, paddingX, px, paddingY, py
  • color
  • backgroundColor, bg
  • opacity
  • width, minWidth, maxWidth
  • height, minHeight, maxWHeight
  • size,
  • overflow, overflowX, overflowY
  • display
  • verticalAlign
  • fontFamily
  • fontSize
  • fontWeight
  • lineHeight
  • letterSpacing
  • textAlign
  • fontStyle
  • alignItems
  • alignContent
  • justifyContent
  • flexWrap
  • flexBasis
  • flexDirection
  • flex
  • justifySelf
  • alignItems
  • order
  • sx

In addition to the above, the Rebass' Tile component also supports:

  • columns
  • gap

With Wallop System, you can use the following props on all components:

  • margin, marginTop, mt, marginRight, mr, marginBottom, mb, marginLeft, ml, marginX, mx, marginY, my
  • padding, paddingTop, pt, paddingRight, pr, paddingBottom, pb, paddingLeft, pl, paddingX, px, paddingY, py
  • sx

Why only three?

  • Typescript: some system props can clash with a valid HTML attributes. For example, size is a valid HTML attribute of an input element, but it's also a system prop. System props support the responsive syntax, and HTML attributes don't. So, <Input size={["small", "large"]} would result in a Typescript error.
  • Best practices: when props are first class citizens it implies that they should be used, but design systems generated by Modulz have already been fully styled, so overrides should be kept to a minimum
  • Predictable: not all system props make sense on all components. For example, passing a fontSize to a Radio wouldn't do anything, since the Radio component doesn't render a text node, but an input
  • Simple API: we want to keep the API surface area simple to learn and consistent across all components

Any CSS can still be passed in via the sx prop, and by default the values are theme-bound, just like system props.

In practice

Now that we've established the key API differences, let's look at how to migrate from one to another:

Rebass

<Box px={[4, 5, 6]} py={[4, 5]} bg="black" color="white">
  <Text as="h1" fontSize={[2, 3]}>
    JAMstack
  </Text>
</Box>

Wallop System

<Box px={[4, 5, 6]} py={[4, 5]} sx={{ bg: "black", color: "white" }}>
  <Text as="h1" sx={{ fontSize: [2, 3] }}>
    JAMstack
  </Text>
</Box>

Have a look at the full migration PR is on Github, where you can see many more examples.

I love how compatible the APIs are. I hope that one day we can have full interoperability in UI systems.