Short guide on starting a Design System for a start-up (feat. Storybook, Figma, and Styled Components)

6 June 2021

This is not one of those posts where I'm going to define a design system, tell you how it's usually created, who responsible for it, and how to evolve and manage it over time. I'm going to approach this from a practical standpoint.

DISCLAIMER: This is a very opinionated post, if you don't feel like using the specific tools I'm listing, feel free to find alternatives, there are plenty. In fact, if you use something else, let me know in the comments, I'd love to see what you're using. 🙃

I have worked for a couple of [realtively] early-stage start-ups that were still in the process of figuring out their style, components, elements, and sometimes even colors. And what I noticed was that the design system was a necessity, not an option for 2 reasons:

  1. Consistency, and
  2. Efficiency

Consistency: Without a design system, your app/site is perceived as amateurish.

You don't want random colors, weird spacing, and border-radiuses creeping onto your design. If you already have some elements with a specific style, then you'd want to make all of your other elements be in the same style. Once you start having pop-ups with different border-radiuses or different functionality, or buttons that are kind of the same blue color, but they aren't, then your app immediately starting to look amateur, not serious, and users start losing confidence in it. And once that happens, the future success of your start-up is on the line.

Efficiency: there are 3 sides to it.

Firstly, the design system helps new engineers to onboard and become efficient faster. Meaning, well documenting what font is used where, what props that button has, and how and when to use drawers, help developers get into the flow quicker without bothering other devs, who can focus on pushing features out for you.

Secondly, once you create a component, you reuse it. If you need more from it, you upgrade it. But you never re-create it over and over again. You never reinvent the wheel. Those components are the lego blocks that you don't need to buy anymore, they're yours to use them. Now, this is a pretty obvious fact for developers, e.g. we always think in components esp. since React came out, but even I, knowing that, sometimes forget, and create another button with a different size, instead of adding size prop to already existing component.

And both of those points lead to the third and most important one: all this time that you have on your hands now, you spend it on innovation. You just got rid yourself of a lot of repetitive tasks, and you now can just spend it on improving processes, finding new tech that may improve your platform, and learning new things.

Let's talk about concrete steps on how to initialize design system thinking in your company.

Start from product and design

Once product/management and design finalize all the pages, features, etc. and you get your links and assets, there are few things you'd want to systematize first

z-index

z-index is subjective. I, personally, like to increment it by single digits, e.g. 1, 5, 8, 10, while I saw other developers like to play with big numbers, e.g. 10, 250, 700, 999. These numbers need to be the same, otherwise, you'll end up with a lot of overlapping each other elements that shouldn't be.

Spacing

Whether it's spacing between sections or the header and the text or grid spacing, these numbers need to be used consistently. You'd always want specific sections to be a certain distance away from other elements and each other.

Layouts

You may want to have <AppLayout />, <InnerLayout />, <Content />, <TitleBlock /> and similar that you'll always be reusing. Your app/site shouldn't change drastically from one screen to another. And if it does - fix it, unless it's one of its features (rarely the case).

Simple components aka basic components aka 'atoms'

I'm talking about atomic design here. There are certain types of elements like <Button />, <InputField />, <Loader /> and others that none of your pages and components can go without. You want them dumb and multipurpose. You're going to use them 100s of times, don't start doing the button over and over again on every new page/feature.

Animations

These get practically always overlooked. How do your animations work? Is it always a random transition property e.g. transition: all 0.2s ease-in-out? It shouldn't be. Consistency with animations is a part of the overall feel of your application. I like doing mines with framer-motion. It allows easily animate layouts, animate onMount and onUnmount, configure preset of animations i.e. make it consistent, and framer has other cool features that I haven't even got the chance to use yet. The point is: MAKE ANIMATIONS CONSISTENT as well.

Icons

Not talking about assets here. All the images and other kinds of graphics can be unique and specific to one page/section.

Icons are separate kinds of assets. You'd want to use them on navbars, buttons, pop-ups, toast bars, and etc. So you'd need to change their fill and stroke colors on hover, resize and do all other crazy manipulations. I would set it up in 3 steps: 1. Create an <IconBase /> component that is a styled.svg component that you're going to reuse for each of the icons. You spread the {...props} there for the root svg element so that you could pass style, width and other HTML attributes as well as your custom ones, like, maybe size or variant and what not. 2. You export icon svg from figma or whatever, put it through SVGOMG (yes, it's quite a lot of effort but it's worth it), and then you 3. Create that specific icon component, and export it from the /icons folder, e.g.

const IconBase = styled.svg` ${switchProp('size', { sm: css` width: 12px; `, default: css` width: 16px; ` })} ` export const UserIcon = (props) => { return <IconBase {...props} viewBox="0 0 22 22"> <path /> <g></g> </IconBase> }

Typography

Text is always the same. So don't be doing font-weight, etc. for every block where the text is not regular. Just have a <Typography /> component and tell it with props what the text should look like. Then style that text with styled.h1, styled.p, and etc.

Colors

If you see color: #bada55; somewhere in your codebase - nuke it. Colors should ALWAYS be used from a theme, even white, because when designers say "white" they might mean #FFFFF7 not #FFFFFF.

Otherwise, when the time comes to update the colors (and it will come sooner or later), you'll be going through ALL the files and updating them manually. Time. Wasted.

How to approach the overall design system

Gradually. Don't go doing ALL of the components and colors you may or may not eventually use. If you're working on a component, if you need it in your feature, then all you have to do is just that, and do so while considering all the values/variables that I mentioned above.

To put a start to your design system, I'd say we'll need Storybook + MDX, Cypress + Percy.io, and, obviously, some styling framewrok, like styled-components or Tailwind.CSS. If you have an in-house designer, I'd go with styled-components. I use Tailwind.CSS when I don't have anyone to help me with design, and/or I want/have minimum involvement from a designer.

So after receiving a Figma or Zeplin link, you

  1. Identify all the colors that are there. Save them to theme.js. Both Figma and Zeplin can list all of them on the right sidebar. Get rid of the ones that look like an "accident".
  2. Browse through all the sections with the designer and identify all possible space sizes, such as between texts, sections, etc. Paddings are a separate thing. Or maybe not.🤷‍♂️ That depends on the design, I guess. Save all those into theme.js.
  3. When it comes to z-index, go through all of the elements you've got on a page, as well as elements that might appear, e.g. toast notifications, and give them a z-value, think about what comes first. Then save those values to your theme.js file as well, you'll be using only those from now on.
  4. When creating a component, do it one variant at a time. If you're working on a button, then create that <Button /> component with minimum props. You'll build on top of it later. Do it in a .stories.* file, render it in a storybook without any context, while keeping the context in mind.
  5. Then, once you're done, use it on a page. If it works great, then create a test for it. Start with Cypress test, set up Percy for visual regression testing. Use jest for all functionality bits, non-visual.
  6. Repeat.

Tips

  1. Push back and question your designer (but not in a dick kind of way)

    Sometimes I notice things in designs that are not worth spending time doing, or there are better simpler ways to do it. Also, sometimes, I notice a new color, while we already have 8 shades of that color. So I'm pointing this out to make sure this is not a mistake, and we REALLY need to add one more color. Oftentimes, we can just use one of the already existing ones.

  2. Don't do tests first. IMHO, in most cases, TDD is a cult. In a start-up environment, you wouldn't advance far enough if you keep doing TDD. That's not a fact, that's just my opinion, based on my personal experience. Feel free to disagree with me, but TDD never worked for me personally. 😅

Anyway, that's what I've been doing for the past 2 years. Seems to work out okay-ish. 🤷‍♂️ Hope that's useful.🙃

©2024 Rail Yard Works LTD is registered in England and Wales, no. 12126621.