CircleCI design system
Historically CircleCI was an engineering-led organization. Design for CircleCI V1 was outsourced to an agency. It did not contain a design system.
When the team started work on the CircleCI redesign in 2018, we started the work on the design system in parallel.
Table of contents
- My Role
- Style / Basics / Theme
Setting source of truth
- Multiple sources of truth: design files and code
- Code as a source of truth
- React storybook as a source of truth
- Setting source of truth
- Setting the stage: Micro frontends
- No dedicated design system team pushback
- Design champions
- Design system team
- Create a visual language for circleci product
- Establish a single source of truth for ui elements that supports a consistent user experience across all platforms and devices
- Provide a scalable framework for design exploration
My role changed over time. In chronological order it was:
- Individual contributor
- Design champion
- Design system leader
- Back to individual contributor
Gor the first few years our design stack contained sketch, abstract and invision which was replaced with figma.
Our code stack initially didn't have separation between front and back end. it was replaced with a frontend stack containing typescript, emotion and react storybook.
Style / Basics / Theme
Styles refer to visual pieces that are used throughout the entire product. This includes colors, icons, spacing and typography. Styles can be viewed as building blocks from which components and patterns are built.
Components are reusable design elements that serve as the building blocks of our application's interface. Components are simply groups of styles. An example may be a button that includes typography, color, icons and spacing styles.
Patterns are groups of components used together to define a complex, distinct section of the product. It often includes detailed interactions around how components work together to create a user experience. A pattern may be a modal, sign-up flow or creation flow.
Layouts are guidelines for how to compose a page by using unified elements and spacing. This outlines how we handle responsive design that should be intuitive using consistent components, grids, and spacing.
Colors are a good example of how complex basics can be. Our process for creating color pallette was:
- Color creation system which can be easily communicated with the team and replicated
- Declaring default colors
A badge indicating the status of a process on CircleCI. This is an example of a component that is reusable throughout the entire product. Same structure used to represent status badges can be applied to all CircleCI components.
Labels are a pattern used to display key & value pairs. Motivation for creating this pattern is that CircleCI displays a lot of metadata that comes from different sources. We needed consistent way to display that metadata.
Setting source of truth
Multiple sources of truth: design files and code
In our first iteration design team created a component library in Sketch. We used Invision to create a clickable prototype, linked component pages together and created a website with reusable components and documentation. We started advocating the usage of design system components in the code.
Developers were confused. The feedback that we got was that the design team's components do not match reality.
- Some components looked differently in design and code
- Some components that we designed were not in code at all
As a first step, we updated our component library to make a distinction between existing and planned components and components that need to be updated to match designs.
Code as a source of truth
We were also exploring ways to use code as source of truth and convert components from react storybook into Sketch symbols. This worked to some extent, but was not reliable enough.
React storybook as a source of truth
Eventually, we decided to declare react storybook as a source of truth for design system components. It is the place where production components live. We added documentation for each component in the storybook instead of having separate documentation for designers. The design team internally still uses the design system project in Figma, but all communication with other teams is done via the design symbol library in react storybook.
Setting the stage: Micro frontends
Engineering decision was to make transition from monorepo to micro frontends. For design that meant that we should have a permanent place (repo) for reusable design components. That would enable developers to pull in components into micro front ends and ensure consistency. It would also enable designers to iterate on components without fear that they won't look and work the same in different micro front ends.
No dedicated design system team and pushback
At the time we didn't have a dedicated design system team, there was no specific team or person responsible for this work.
- Engineering feedback at the time was that having separate repo with reusable design components is not directly creating value for customers. We were under a pressure of delivering where speed was valued more than perfectionism.
- As additional argument developers stated that they prefer to initially hardcode specific component, reuse it a few times, and when they see how it behaves in different scenarios they extract it as reusable component.
Hardcoding components in micro frontends and reusing them from their non-permanent location for me meant creating a technical debt that increases with every usage. It is also a blocker for the design team. The design system is not a static thing that you create and forget about it. It constantly evolves. Not having a single source for reusable components meant not being able to update them easily.
I also did not agree with thinking that we should hardcode components and wait to see how they behave in different scenarios. Product designers have much more context about how components will behave in different scenarios long before developers because we do future design explorations and have ideas on how future designs will connect with existing ones.
Not having a dedicated team to execute the design system into code made us create an unofficial design champions team formed out of a few designers and developers. We worked together on code and made incremental progress.
Design system team
Forming the design system team was a light at the end of the tunnel for the design team. Their job was not just to code missing components, but also to replace all instances in the product where components were hardcoded.
Product designers joined forces and split work on component documentation. We reviewed documentation as a team, and every designer contributed to adding documentation to the codebase in the storybook.
- Start from the design system even if it's incomplete. It's not important to have the design system figured out completely, as long as components live in their permanent locations in the codebase.
- No one will do the work if there's no person or team responsible for it. We made a tremendous amount of progress in a short time after we got a dedicated team to execute the design system work in code.
- Be flexible. If the current context is that organization can't make a lot of progress on the design system, seek ways to make incremental progress and keep moving in right direction.
- A design system is a living thing. Do honest best work. As the team's knowledge about product, design and customers increases iterate based on new learnings. Win or learn.