Friend, my first design system took 3 years to build. My last just 3 days. Here’s what I learned.

First, what is a design system anyway?

A design system is the ideal workflow for UI. A set of core reusable elements and rules that spit out good-looking interfaces without design skill on your part.

You and your designer set the tone once, create the elements, some basic rules, then you work from mockups. Everything you build looks perfect and your designer spends time on UX not fiddly details.

You the engineer can build perfect UI from a napkin sketch.

๐Ÿ˜

That’s the theory.

Life is messy so a good design system must also be flexible. Local over-rides for one-offs.

Prereqs

You’ll need a couple prereqs before you get started:

  1. A designer that agrees systems are good. Some designers see their work as art. Every element is custom, every button a little different, every screen a new masterpiece. You can’t systemize this. You will suffer. Sorry.
  2. A componentized approach to UI. Use a component-based framework like React, Vue, or Angular. You can do it with CSS classes but this is easier. Trust me.

The main benefit of components is that you can encapsulate both UI and UX. Not just looks but also behavior.

PS: I got lucky and get to do this from scratch. You can introduce a design system gradually but it’s a little trickier.

Goal

Every select field, say, should look and feel the same. Across your entire app. So why build it from scratch every time?

You want something like this:

Click through for source

And that’s your standard beautiful magnificent and all round marvelous select field.

Build it once use it everywhere. โœŒ๏ธ

Test it once, approve it once, back-and-forth with designer once, back-and-forth with QA once, back-and-forth with PM once … and then it works forever. You’re good until the next redesign.

And with a little luck any future redesign will touch just your design system. You might not even have to touch any application code.

the_dream giphy

Where classes โ€“ utility classes especially โ€“ fall down is this reusability. Do I have to add bg-gray flex1 color-blue p3 or was it bg-gray flex2 color-white p4 ๐Ÿค”

Stop. You’ve already lost.

Every QA cycle, every PM test, every new feature you will have to carefully vet every little detail. Because they’re always done from scratch.

A design system saves you that effort.

How you create a design system in 2020

3 years ago when I started building my first, the ecosystem wasn’t quite “there” yet.

CSS-in-JS or CSS modules? Big fat CSS classes or utilities? React, Vue, or nothing? How to scales? How to colors? Weird names or long names? Build a catalogue or not? How do you docs? Do you even need docs?

Crap, what about responsiveness? Do you grid or flex? float: left?? ๐Ÿคจ

I’ve tried it all.

This is what I’ve landed on as the ultimate solution:

  1. Use Storybook โ€“ spits out a catalogue and docs too. Live preview of your components, human readable descriptions with docs, you can even just write documentation in MDX and storybook handles the rest. Hell it even spits out API Docs based on TypeScript types. ๐Ÿค˜
  2. Add Chromatic โ€“ a SaaS from the creators of Storybook. Gives you a hosted versioned Storybook. Added bonus: snapshot testing of all your components. Screams at you when there’s a visual regression ๐Ÿ˜
  3. Use TypeScript โ€“ the VS Code experience with TS is just wonderful. Hints and docs as you mouse-over a component are fantastic. Very helpful when you work on a team.
  4. Start with theme-ui โ€“ this part is React only. theme-ui is the best balance between developer experience/ergonomics and solid design system. Does most of the work for you.

I started from scratch with npm install @storybook/react --save-dev and 3 days later had a full custom design system โœŒ๏ธ

The trick is to lean hard into the ecosystem and let others do your work.

Here’s how

  1. Install all the dependencies
Click through for source

theme-ui is your only real dependency. The rest are used in development.

Don’t worry about the low version number on theme-ui. It builds on lessons learned from several earlier attempts.

@jxnblk did a great job

  1. Configure storybook to be fab

Storybook by default is great. Storybook with some addons is fantastic.

The most important parts for me are:

  • easy/automatic documentation
  • accessibility checks
  • knobs to visually test components
  • typescript support

Configuring all this happens in the .storybook directory.

Click through for source

Some addons like to be included via the addons.js file. Others go in main.js. I still don’t understand why.

Click through for source

This configures defaults for every story in your storybook. That is every example you want to put up. Things like adding the theme provider, enabling knobs and accessibility checks, etc.

Click through for source

This part adds the documentation addon, support for typescript, and MDX.

MDX is important because it means you write your design system descriptions once and they double as both testing and documentation. It’s great.

  1. Customize theme-ui for your design

This is the fun part.

theme-ui actually does all the work for you. As long as you don’t need custom behavior.

It comes with more pre-built components than you can shake a stick at. All the components you’ll need, really.

And it supports themes for custom coloring, spacing, etc. All you gotta do is configure a custom theme for your organization.

Something like this:

Click through for source

Custom colors are the quickest way to achieve a great custom look.

I recommend giving them color names. Primary/secondary/accent gets confusing fast. Especially when variants are in play.

You should map primary to color so theme-ui default components pick up on your colors. This saves you time.

  1. Customize theme-ui elements

Once the basic scales are in place, you gotta apply them to different elements. Rather than creating your own from scratch, tell theme-ui what to do.

A custom input, for example.

Click through for source

And a custom form falls out โค๏ธ

  1. Use your design system

The best part is that you get to use scales. Scales that you defined in your custom theme.

Look at this input definition, for example:

Click through for source

Lots of magic numbers right? They map to the size and space scales.

Click through for source

pr: 3 means padding-right: askTia.space[3] ๐Ÿ‘‰ 16px

Same for color scales. You say greyVeryLight and theme-ui checks the color map to get the digits.

And if you need to do something custom, there’s the sx prop.

Click through for source

Some elements come with helper props. bg is very common, variant is another.

Beyond that, the sx prop lets you define everything you’d otherwise use the style prop for. Except it goes through your theme config.

Also great for adding dark mode. Change theme. ๐Ÿค˜

Happy Friday

Cheers,
~Swizec

Learned something new? Want to improve your skills?

Join over 10,000 engineers just like you already improving their skills!

Here's how it works ๐Ÿ‘‡

Leave your email and I'll send you an Interactive Modern JavaScript Cheatsheet ๐Ÿ“–right away. After that you'll get thoughtfully written emails every week about React, JavaScript, and your career. Lessons learned over my 20 years in the industry working with companies ranging from tiny startups to Fortune5 behemoths.

PS: You should also follow me on twitter ๐Ÿ‘‰ here.
It's where I go to shoot the shit about programming.