Design Systems: Introduction
November 28, 2019
Let’s talk design systems! Over the past three years, I’ve been surrounded by design systems. At Toyota Connected, I helped build the design system called Loom (you can see the talk I did at EmberConf 2018 on YouTube). Now at LifeOmic, I built our design system, Chroma, in React. I thought it was a good time to go ahead and just write up what I think about design systems and why they’re helpful.
Web app development typically starts very small. Your app is very focused and concise. At some point, it goes through an organic growing process (as it should!). As more features get added on, inconsistencies begin popping up. Developer A may like using a certain padding, while developer B thinks a different size padding looks better. Developer A prefers larger sized text, while developer B prefers smaller. As more developers come on board, they may introduce new inconsistencies based on their experiences. What inconsistencies am I talking about? Let’s have a look at some.
Differing Spacing Values
Above, we have our example app where one developer prefers spacing of 16px in the main content area for their page, while another prefers 22px on their page. With no agreed upon spacing values, it’s up to the developers to determine what they think looks best. On the surface, this may not seem like a big deal; however, take into consideration the different spacing now on two different pages. When a user browses to page 1, with the 16px content, and then to page 2 with the 22px content, they’ll notice a shift in their content. This is just one small example, but I’ve seen this extrapolated across an entire application. I’d say this is a very common issue among app development.
Too Many Font Sizes
I’m going to pick a bit on Material-UI’s site, just because I think it’s a great example. Notice how Twitch’s font size options are very locked-in, in comparison. Their scale makes a lot of sense to me, as they don’t have extremely similar sizes. It seems like they really went through their typography scale with a fine-toothed comb. Now let’s look back at Material-UI. They have a lot of very similar font sizes and a lot of them! To me, it seems like they could do some consolidation. For example, the fact they have a 0.9375rem font is a bit odd - just go up to 1rem or down to 0.875rem! Being able to consolidate your font sizes to a scale that makes sense, while not providing too many similar options helps cut down on inconsistencies in your app.
Too Many Options
Let’s take a look at a buttons example. Noticing a pattern by now? There are way too many button options and many of them are very similar.
“But wait… why are these examples bad?”
Aren’t you limiting people’s imaginations? Too many options in an app makes for a bad user experience and ultimately bad for your company’s brand. It can get out of control really fast if you’re not careful. We all know sites we hate going to because it’s clunky, or maybe ugly, or just a pain to use. For example, I switched banks purely because one mobile app was way better than what I was currently using.
Folks enjoy using web apps like Slack, Spotify, Twitch, etc. because they have consistent patterns. You don’t necessarily realize it, until you start looking into the details. That’s because they do a great job at following their own patterns and other existing, established patterns on the web you’ve grown to be accustomed to.
Let’s talk about:
“Aren’t you limiting people’s imaginations?”
Well, maybe. Kind of? It depends. Here’s my hot take incoming… For most web applications, the goal of your app is to deliver value to your user. If your app is not a bleeding-edge art web app, I’d argue that yes, limiting people’s imaginations is a good thing. Design systems create patterns, not one-offs. Users enjoy patterns. Stick to patterns! I’m not saying don’t make your web app look exactly like something already out there, I’m just saying don’t go too crazy.
Let’s talk about the developer experience of an app growing. If patterns are not put in place, it makes it a lot harder to onboard developers if they see 10 different ways of doing things. How do they know “what’s right?”. This can be really difficult. There are some excellent developers as well who are great with solving Computer Science problems, but when it comes to building out nice looking UI, they struggle. How can we help bridge the gap?
Meet Design Systems
Adding new features to your app, or growing your team isn’t a bad thing, by the way - that’s what is supposed to happen! The question I’m asking is how can you and your team wrangle in the UI/UX inconsistencies, while also creating a better developer experience? How can you establish patterns so that your web app looks like a great product that folks will enjoy using? Well, squash the inconsistencies and create a design system!
A design system consists of a design language, a shared component library, and documentation. It’s a collaboration between designers and developers to agree on a set of constraints for the application. From font sizes and colors to components like buttons, inputs, modals, and more. It’s a way to allow developers and designers to quickly iterate on new features, or new applications entirely, while maintaining consistency. Let’s dive more into detail on this…
Start an Audit, Trim the Fat
At LifeOmic, when we set out to built our design system, our designer and I did an audit of our app and looked at all the different font sizes, font weights, and colors used. We started with these three, as they would help lay the foundation for components as well. It’s important to nail down a typography scale and a color palette. Once you have these two things figured out, the future work makes it a lot easier to pull from this bin of information.
So yeah, we audited the app, and figured out what we used the most. Just like using CSS Stats above for Material-UI and Twitch, we did a similar process. We cut the things that were one-offs, or were used very rarely. We looked at awesome tools like TailwindCSS to see what their scales were, and adapted ours. We wanted to ensure there were enough options to fit our use cases in the app, but not too many that it’d be hard to decide on what to use for different use cases. For typography, we landed on 7 different sizes and 3 weights. I then went through the entire application and updated every use case of font sizes to match a value from our scale. The app instantly got a lot more consistent!
Next, we did the same thing with colors. We took an audit, figured out a color palette we wanted to use, and started updating the app. For our colors, we really only used black, gray, blue, red, and green with each color having 8 shades. Rinse and repeat, updated the app, and boom, it looked even more consistent!
After typography and colors, we moved on to buttons. We had too many colors, sizes, and variants for buttons. We were initially built off of Material-UI, and in my opinion, they just provide too many options out of the box. Ultimately, we settled on only one color of button (primary), one size, and three variants. The three variants were contained, outlined, and text. Having these three variants allowed for enough differences between the buttons and their roles, but to keep things clean and not offer too many options. The entire app was updated to only use this new button component with one of the three variants. Once again, eliminated more inconsistencies!
After these items, we then moved on to more of our React components. We picked a component we used a lot and put constraints on it. After that component was done, we moved on to the next. We did this enough times to create a component library. The components in Chroma are what I call “foundational, base level, presentational” components. They aren’t tied to Redux, or making API calls. They typically have very little to no state associated with them. They just take in inputs, and give you an output of DOM element(s). Think of typical elements you use on a site - text, buttons, tooltips, modals, popovers, etc. - these are all components in Chroma, our design system.
The last piece of a design system is documentation. Storybook has been wonderful for us for this. People need to see these components in action, see how they can import them, and code examples. The big part in driving adoption with other developers, in my opinion, is this bit. If your documentation is really good, fellow developers will want to use these components because they’re well documented and almost “plug and play”.
The documentation should also describe the why and how of the component. Work with your design team to establish rules, such as “why use this component over this one?“. What’s the purpose of each component? When should you use one button variant over the other? Establishing this really helps declare the intention for each component. It also helps your designers ensure the component has a purpose, which itself can help making the realization that maybe you don’t need that component anymore, because there’s something similar you have already!
What About Designers?
Design is obviously a very important piece in all of this. At each step of the way, you have to be working with your designers to ensure you’re on the same page. A design system and creating these patterns also helps bridge the communication gap between developers and designers. Sometimes designers refer to things differently than what maybe you call them (for example, they may refer to box shadows as elevation). This sounds really silly, but once you have a design system and name for things, you’ll start speaking the same language.
Similar to us developers, they also have these components built out in Figma. Figma makes it really easy to do all of this. The typography scale is in Figma, alongside the color palette, alongside all of our components. For example, our Button component uses a font size from our scale and a color from our color palette. These things compose together to build other components. When it comes time to design out a new feature for the app, we normally just drag and drop existing components onto a page for most features. Other features take a little more UX thinking and may be a little different; however, they’re all built using the components in our library.
Put the Design System to Work
Okay, now you have all of this stuff. Now put it to work. When it comes to designing or developing a new feature, use components out of your new toolbox. As time goes on, designers or developers may be tempted to create a new, shiny component that’ll create a different pattern. That may be okay — discuss it with your team! It may be a new pattern/component that gets used in one spot, and then begins being in other spots in the app as well. If that happens, you know what to do - think about making it part of the design system.
At other times, someone may just want to build something new and shiny, that has an existing pattern. The design system keeps both designers and developers honest and in-check. Since it’s used by both, a developer should be free to say “hey, can we use this component we already have instead?“. On the flip side, a designer can say the same thing to developers. As always, just discuss it with your team and go from there!
Ultimately, in my opinion, the advantage of a design system is worth the time investment. From an external perspective, it helps your web application look great and be consistent from a UI/UX perspective. It’ll help establish your brand from a design perspective as well. Internally, a design system will help your developers move faster and more efficiently. It will help you and your team establish design-approved patterns, and eliminate one offs. It’ll help new folks joining your team be able to hop in and contribute very quickly to feature development. If a designer is busy and can’t create high-resolution designs right away, your design system should be a toolbox for a developer to build it out on their own. Overall, a design system is about consistency and efficiency.
Whew, that felt like a lot! I’ll let this all sink in for a bit and I’ll write more at a later date. My next post will be about themability and how we built Chroma to work for multiple different LifeOmic products. Until next time! Cheers!