How We Build a Component Design System

Building a design system with components to standardize and scale our UI development process.

Jonathan Saring
Bits and Pieces

--

In this article, I will show and explain our process of creating a design system. I will share real examples every step of the way.

Design systems were created to bring order into an inevitable entropy. The first design system was introduced by NASA in 1976, and today nearly all large organizations like Uber, Pinterest, Airbnb, or Shopify have such a system to bring consistency into the chaos of more products and teams.

At Bit, we build tools for 150,000+ developers working with components. Our platform helps developers build, share, and collaborate on components to speed up and improve web application development.

We enjoy a Design System driven by Components.

Over the past 2 years, we’ve been “dogfooding” our platform to build a design system and turn it into a living ecosystem of shared modular components.

The benefits of our system go way beyond UI/UX consistency. We greatly accelerated and scaled our development, improved our product quality, and greatly improved work between developers, designers, and everyone else.

By letting everyone create and share components in a collaborative way, we are able to achieve faster and wider adoption of our design system.

In this article, I will focus on the developer side of things and will share our goals, process, and results. Feel free to AMA in the comments below.

  1. Visual Language
  2. Shared Components
  3. Documentation and Discovery
  4. Incremental Upgrades
  5. Rippling Changes to Dependencies
  6. Project Updates
  7. Team Communication
  8. Designer — Developer Collaboration

Also worth reading:

1. Our Visual Language

Audit, then order.

Our process of creating a visual language was a bit different than what you would read in most articles on design systems. This is a privilege saved for larger enterprises and is often a luxurious choice for younger companies.

As a growing company, we didn’t have the time to stop and turn our design system into a large and complex project. Instead, we had to audit and turn our existing visual language into an organized system.

This process, led by Bit’s head of design Amir Shalev, was twofold: First auditing our existing styles and elements, and then creating a consistent system to standardize our visual language as a strong yet flexible base.

Our surfaces and colors used in bit.dev

Visual consistency means creating a unified style-guide standard for colors, fonts, sizes, positions, and every other part of your visual language. Aspects such as typefaces, typography, primary and secondary colors can still be specified as part of the design system.

In addition, we needed to create a consistent set of UI elements that can be later implemented as components using a modern framework (e.g. React).

Our buttons, avatars, and other basic components

To make your system of elements actionable in the real world, it must include more than just a set of basic UI components like Button or Avatar. It should include concrete examples of more specific instances or compositions of components, which are the most basic implementation of your features.

Composition of components to create more concrete and advanced features

The design of your system is not ready until you have two assets:

a) A style-guide that defines the styling and implementation of your UI. This is usually a rather long document with a lot of text and typography.

b) A set of reusable visual elements that bring together both visual (UI) and functional (UX) consistency through components. This is usually a rather large canvas with elements drawn on Figma or Sketch etc (we use both).

2. Shared Components

Building a component ecosystem.

Some people just publish a single-versioned package with all their components. We prefer creating a shared component ecosystem.

Our process

If you head over to the homepage of Bit.dev you will see something awesome. When the mouse hovers over a component, a highlighter will turn on, indicating the component's name, version, and parent Scope.

The Bit.dev homepage — a composition of shared components

What you see here is a page composed of shared components. However, these are independent components developed and owned by different teams and published from different projects, which are mixed and integrated together.

At Bit, we have more than just one design system. We have different teams that build and share their components, in a UI component ecosystem.

If you hover over components like link or paragraph and click the links, you will see that these components are part of the “base-ui” Scope. This is our most basic design system, developed by our design system team in an autonomous GitHub repo, and published to Bit.dev for everyone to use.

“Base-ui” — Our base design system components

The marketing team, however, needs some more concrete components like a marketing “heading” or “action-button”. These are not a part of the base-ui design system but are a part of another Scope called “Evangelist”. They belong autonomously to the marketing team in this GitHub repo. Since they use components from base-ui, they get updates from the base-ui team.

“Evangelist” — Our marketing components

Evangelist is just one of many Scope of components that compose and extend the base-ui components. In fact, each team in the company builds and shares its own Scope of components with everyone else.

Instead of publishing a single one-size-fits package for components, we create an ecosystem where everyone works together yet delivers independently. The design system’s team role is to facilitate and regulate, not block or enforce.

This turned out to be a huge success, and we were able to reduce the building time of new marketing pages by ~75% while keeping our design consistent. Try visiting the bit.dev/enterprise page or /support pages to see examples. Similar success was recorded by many other teams in the company.

Working with our own tools

Our own “dogfooding” of Bit means we build the way we help other people build. We’ve been doing so for a few years, since 2017. Here’s the gist.

  1. We use Bit’s OSS Workspace to develop, manage, and publish decoupled components in different codebases owned by different teams.
  2. We enjoy Bit’s cloud platform to help all teams smoothly expose, share, and integrate components with each other.
  3. The design-system team provides our base components, controls updates, and regulates changes to ensure consistency and standardization.

Choosing React

We chose to use React back in 2017 for a variety of reasons, and have been very happy with our choice. Since the introduction of Hooks and Context API in React 16, the ability to decouple components from each other even in terms of state management, for example, has become phenomenal.

Yet, we’re seeing many teams choosing to use Bit for Vue or Angular and even Stencil Web Components. We’ve even been working with the Angular team itself to provide support for Bit with Angular. After taking everything into account, we believe React is the best solution for us at this point.

Independent components

Bit workspace helps you build modular projects, while enjoying a simple and holistic dev experience. Each component is independently developed, built, tested, documented, published, and integrated into new applications. All components are composed and managed together in harmony. Try it.

Standardizing development

Another great way to achieve consistency in design is to standardize the development of components. Bit helps us do so with a variety of features such as standard component dev environments, reusable docs templates, and even extensible and reusable build pipelines to standardize the release process.

Customizable, extensible, reusable build pipelines

3. Documentation and Discovery

Always up to date. No extra tools.

Another advantage we have when working with Bit is that we don’t need to create or maintain extra documentation websites for components.

Local development

As we write components, Bit’s UI presents the documentation for every component in the local development environment. This includes descriptions, examples, and even compositions that render the component in isolation.

You can create customizable and reusable docs templates so that all components can be documented by the same standards and design.

Docs are a part of local development

Docs on the cloud

Docs are just a part of every Bit component. When it is exported to the cloud, its docs become the front-page of the component for everyone to see. Docs can be viewed and explored in the same place the component is hosted. If you install or import a component, you can locally develop the docs too.

“Tokens, then React, UI Kit, then Doc Site for changed links to those + release docs”

— Kaelig Deloumeau-Prigent, Developer, Shopify’s Polaris

All the docs on Bit.dev are exactly what we see when we develop locally. With every new version of a component, its docs can be easily updated too. No extra overhead, no complex processes, no outdated documentation.

What you develop locally is what you get on the cloud

Discoverability and search

And as we have more and more components, Bit.dev makes components discoverable with features like component-search and context-filters that help us instantly search through many components with ease.

Head over to bit.dev and search thousands of OSS components, or add your own

4. Incremental Upgrades

Independent component versioning.

Our design system is versioned by component, and not as a single package.

Versioning independent components is much better than versioning all components as a single package. Independent per-component sem-ver has been a game-changer for us. I’d also suggest reading this wonderful post by the awesome Nathan Curtis. Here are the key advantages for us:

  1. We only get updates you need to the things you use.
  2. We easily and quickly upgrade a single component.
  3. We easily hotfix or rollback any component.
  4. We mix and match components to create anything.

Bit helps us version and publish each component as an independent package. Since each component is versioned independently, our different projects can get incremental upgrades to components, instead of just one large package.

If you head over to this button component you will notice that it is currently on version 1.5.0, and started on version 1.0.0 a while back.

This gives both our designers and developers great freedom to constantly innovate and release upgrades to production.

For example, here is version 1.5.0 of ‘button’ used in production.

Evangalist/button@1.5.0

And here is the previous version 1.4.0.

And here’s the earliest version 1.0.0 of ‘button’.

Evangalist/button@1.0.0

If you head back to version 1.5.0 you will notice that it has an array of examples that support more design use-cases than ever before.

Our designers and developers are able to freely innovate and deliver upgrades without having to wait on large bloated versions or long releases.

Component developers can control each component’s version bumps according to sem-ver rules, view its history, and even its view changelog.

App builders don’t get updates they don’t need. Everyone is happy.

5. Rippling Changes to Dependencies

Managing all component relationships.

Bit manages the dependency graph between all components in a project. This means that when we upgrade or break a component, Bit will “know” which other components depend on it, and will run their builds and tests.

As a result, it becomes much easier to develop many components inside a single project, since it’s easier to master their internal relationships.

“If we upgrade and break a component, we have to go through and fix all the dependent components”

— Jony Cheung, Software Engineering Manager, Atlassian’s Atlaskit

On every change, the builds and tests of all dependant components will run and let us know exactly what’s broken and what’s not. If all is well, we can simply tell Bit to bump all dependant components at once.

We’re now working on a new product called Ripple CI. Through the cloud, Ripple’s build process will propagate changes to all dependant components in all of the organization’s applications. We (and you) will be able to see exactly how every component is impacted, where, and how, then fix and release (want to learn more? ask to get in our Beta program).

6. Project Updates

Automated with a GitHub Integration.

We use a publically available integration to connect Bit.dev with GitHub. When a new version of a component is published to Bit.dev, it will “know” which GitHub (or GitLab) projects should be getting this update.

Then the process becomes fully automated.

The new version of the component is sent to all-consuming projects as an automated Pull-Request that can be accepted with one click.

This makes it very easy for our design-system team to continuously deliver upgrades and help all product-builders accept and integrate the changes.

And, our design system team can monitor who forgot to update what and where at all times. Here Gilad Shoham who leads our core team just avoided a serious nudge! Watch out Gilad, we see everything.

7. Team Communication

Automated with a Slack Integration.

When a new component version is published, all teams that use this component (i.e. have this component as a dependency) will get an update notification via the platform and also via a Slack integration.

So, for example, when a version of ‘button’ inside ‘shopping-cart’ gets exported, our team gets a notification that includes the user’s name, the type of action (export), the number of components related to that specific action.

Here Eden Ella from the Envagalism team is caught upgrading buttons.

When importing, the same notification shows but with the origin Scope.

This workflow helps everyone stay in sync and work better together.

8. Developer — Designer Collaboration

Working together over code, in a visual way.

A design system means different things to designers and developers.

Designers usually talk about elements on their canvas. Developers talk about the React component in their IDE. Users will get the code, not the design.

That’s why it’s critical to include designers in our UI development process.

We use two great tools to achieve a firm, mutual handshake.

The first is Zeplin — Which is a great way for designers to work with developers. We use to translate and organize design tasks into development tasks, and we work with it every day.

The second is Bit — Which is a fantastic way for developers to work with designers. It creates a bridge for our designers to take an active part in the development of UI components. Moreover, helps our designers to monitor and collaborate on code changes and new versions of components.

💡 The Zeplin and Bit teams are now working on a joint integration!

Designers can see and try the actual React components in a visual way

We use Bit to expose all our components to our designers and help them always make sure everything stays perfectly aligned with the design.

Features like hot-reloading rendering and editable examples are a great way for designers to view components, and even try different designs hands-on.

When there’s a new component published to Bit.dev, or a new version of an existing component, designers can instantly and visually see what changed. That makes it easy to ensure everything stays consistent with the design.

Then, after designers approve, the change can be sent as an automated PR to all projects affected by the change. This means our designers now work with developers directly on the development of components. Cool, right?

In the near future, our team intends to add more designer-facing features to Bit.dev such as an interactive property panel, so designers can create changes to components, and save them as new versions. Should be ready in 2021.

Conclusion

NASA’s Design System 2020

Creating and keeping a consistent UI/UX across every touchpoint of your products helps users intuitively navigate, and successfully interact, with different parts of your applications without confusion. It’s your brand.

You need a good brand.

In our process, we have been creating a design system from the ground up. We audited the existing design, then turned it into an orderly system that defines our visual elements and styleguide, which tell our Brand’s story.

We rely on our own tools cloud platform to create a system of shared components that brings everyone together in the process. We let components drive the development of our products, in a democratized yet regulated ecosystem. This system gets fast and almost absolute adoption.

I hope this helped you learn a little bit about our process and the possibilities that exist out there to build web applications together in the modern world.

We’ve been helping many really great teams build their own systems in a similar way, and please feel free to reach out to us and ask anything!

Thanks for reading 🍻 🎨 ❤️

--

--

I write code and words · Component-driven Software · Micro Frontends · Design Systems · Pizza 🍕 Building open source @ bit.dev