Developing Design Systems: first steps

Răzvan Roșu
ING Hubs Romania
Published in
5 min readJun 27, 2023
Photo by Jukan Tateisi on Unsplash

Since you are here, I assume that you are familiar with the concept of Design Systems. Otherwise, you can check out my previous article, Planning, designing, and developing Design Systems and return afterwards.

In this article, I’ll guide you through the initial steps of developing your own design system by implementing a Style Guide and a Component Library.

In order to understand the process of building a design system, let’s take a quick look at how we typically create digital products:

Product Infographic

It all begins by converting our brand guidelines into a Style Guide. This guide outlines the visual elements, such as colors, typography, and iconography, that represent our brand identity.

Using the rules and specifications defined in the Style Guide, we move on to developing one or more Component Libraries. In today’s industry standard, designers work with Figma components, mobile developers have their iOS and Android components, and web developers have their own set of components. Each Component Library consists of reusable building blocks that align with the Style Guide.

Now, here’s where the Design System comes into play. It provides comprehensive guidelines on how and when to use the components from each Component Library. These guidelines ensure consistency and coherence across all digital products created using the Design System.

With these foundational elements in place, we can create homogeneous products, such as mobile apps and web apps.

1. Style Guides

Let’s recap what Style Guides are and their significance:

A Style Guide is a collection of predefined rules that designers and developers follow to ensure consistency across apps, websites, and print materials. It encompasses various elements, such as color palette, typography, grid system, spacing, iconography, imagery, and tone of voice.

From a developer’s perspective, a Style Guide can be defined as a collection of predefined rules known as design tokens. Design tokens include values for colors, font-related attributes like size, weight, line-height, vertical rhythm, grid-related attributes such as columns, gutters, bleed, spacing values, icon assets, and image assets.

When it comes to storing design tokens, there are multiple options to consider:

  1. Native CSS variables: Values are defined and accessed through the :root pseudo-selector, making them accessible to components.
  2. CSS classes (e.g., TailwindCSS): By defining design tokens in a configuration file, a build process generates CSS classes systematically, which can then be used in components.
  3. Preprocessors (e.g., SCSS): This traditional approach involves using preprocessors to define and store design tokens.
  4. JS-in-CSS: Design tokens are stored as JavaScript variables, which are then imported and used within CSS.

Each option comes with pros and cons.

Have in mind that a style guide is subject to change (new variables will appear, others will be deprecated and values are subjected to change).

Here are a few tips to consider when working with Style Guides:

  • Use agnostic variable names that are independent of specific design choices.
  • When implementing a dark mode/light mode strategy, check if the dark colours have a ratio of 1:1 with the light colours

2. Component Libraries

As a developer, it is important to have the ability to reuse components across multiple projects. To achieve this, we can store our components in a separate repository. I recommend using a mono-repository setup, which allows us to version each component individually.

In addition, it’s valuable to have a comprehensive view of all the available components and their various states. This can be achieved by using a tool such as StorybookJS (alternative options include Ladle, Vitebook, Fractal, PatternLab, etc.).

tools

Here are some real-world examples of organizations that have implemented component libraries:

When it comes to developing components, here are some tips to keep in mind:

  • create components based on needs
  • once in a while pick up a nice to have component/functionality
  • define components with gradual complexity;
    consider using a methodology such as Atomic Design.
  • constantly curate/refine existing components.

Setup

Let’s assume that we have our Design Tokens and we have decided to use StorybookJS for our Component Library.

Here are the key parts of our mono-repository’s package.json file:

{
"name": "my-monorepository",
...
"private": true,
"workspaces": [
"packages/*"
],
"devDependencies": {
...
"storybook": "^7.0.18",
"tailwindcss": "^3.3.2"
...
},
"scripts": {
"storybook": "storybook dev -p 6006",
...
}
}

You’ll find below the key parts of our folder structure.
You’ll notice that we store the components in a packages folder.
Each component has it’s own package.json file. Inside we specify it’s version and dependencies (be it other components from the mono-repository or external dependencies).
In the folder stories we will define our component’s cornercases.

├── node_modules
├── packages
│ ├── child-component
| | ├── ...
│ | ├── node_modules
│ | └── package.json
│ ├── my-button
| | ├── ...
│ | ├── node_modules
│ | └── package.json
│ ├── my-card
| | ├── ...
│ | ├── node_modules
│ | └── package.json
│ └── parent-component
| ├── ...
│ ├── node_modules
│ ├── package.json
| ├── ParentComponent.jsx
│ └── stories
│ └── ParentComponent.stories.js
├── index.js
└── package.json

For our TailwindCSS setup, we store our Design Tokens in the tailwind.config.js file located in the project root. Here’s an example configuration:

module.exports = {
...
theme: {
colors: {
grey: {
300: '#ecf0f1',
500: '#bdc3c7',
700: '#95a5a6',
900: '#7f8c8d',
},
...
spacing: {
'sm': '8px',
'md': '12px',
'lg': '16px',
},
...
fontFamily: {
'sans': ['Helvetica', 'Arial', 'sans-serif'],
'serif': ['Times New Roman', 'Times', 'serif'],
'mono': ['Courier New', 'monospace'],
},
fontSize: {
base: '16px',
300: '12px',
500: '16px',
900: '24px',
},
...
}

With TailwindCSS, predefined CSS classes are generated based on our design tokens. For example, the font color #7f8c8d from the configuration corresponds to the CSS class text-grey-900.

To conclude this article, I’ll provide a complete DEMO that includes a mono-repository boilerplate (here) and a project boilerplate (here). Both use ReactJS, but you can easily adapt them to your preferred framework.

In the next and final part of this series, we’ll explore an exciting aspect of design systems: integrating web components to achieve framework-agnostic component libraries.

--

--