ZenHub's Dark mode

Revamping ZenHub's design system to support theming and develop all-new best practices
Project Overview
Designing to support theming for ZenHub required refactoring of our design system before jumping into what dark mode is today. This not only helped making developer handoffs easier by saving developers time, it created parity between Figma and production and designers now design with systems at scale in mind.
Read more details on this blog post I wrote.
My Role
Design lead
July 2021

The problem

As a developer-focused product, it wasn't a surprise our customers wanted dark mode support when facilitating agile ceremonies with their teams within ZenHub. So when the team started to look into how we would execute this project from a technical and visual standpoint, it was apparent we had to tackle the elephant in the room: design system debt. Our component library in Figma was off from what you'd see in production, and if we wanted to achieve theming in our product, we had to standardize our design system to be aligned with our code.

But how did this happen? As designers, it's natural that we want to design with the best user experience in mind. And even though we have feedback sessions with developers to discuss complexity and project scope, sometimes our design can stray from our code's design system. Before long, you're left with design debt that's significantly slowing down development time, creating bottlenecks, and doubling the workload.

For full transparency, here are the two main issues we recognized within our design system:
Challenge 1: An unclear color scale library

Our color styles were out of sync with production, sometimes we would use hex codes and developers would have to find a matching variable.

The color library we used in figma

The color scales available to use in production

Challenge 2: Our component library didn’t match what was in production

Components in our design system were ahead of production. Meaning, our design system had the patterns the design team wanted to be implemented in the product but weren’t in production yet. This became a problem for our development teams as refactoring components creates added risk and could make QA difficult since the component that should be tested in production may not meet the expected behaviour.

Like many other fast-growing companies with a small but scrappy design team, there was no time (or budget) to spend resources on updating our design system. Regardless, our design system structure was becoming a blocker to our development teams being able to ship faster.

Calendar component in Figma

Calendar component in production

How we revamped the design system

While the challenges in our design system were obvious, finding the time to retroactively go back and amend these issues was the true challenge. However, we knew this work needed to be done sooner rather than later to make room for dark mode. Here’s what our team did to solve our problem.

Start, stop, continue
1. Clear design token properties

Design tokens are all the values needed to construct and maintain a design system — spacing, color, typography, object styles, animation, etc. When we pulled out our colour library in production, the team was shocked at the inconsistency between how many colors existed in production vs. what we thought we had available in our library. Taking a closer look at this helped us learn what terminology we were using, what was working, and what wasn't.

In partnership with our visual designer, we created the color palette we wanted to use moving forward. These colors were variants of our branding and were tested for color blindness.

2. Better terminology that scales

Semantic libraries are easier to understand, that's why we moved away from purple-light, purple-lighter. If you work on a design team, you probably have had to explain your files to your colleague when they are working on them. Things like what color do we use for CTAs or which of these is used for the alerts?

We mapped the old scales to the new ones for our dev team to know what would be migrated.  

3. Using a design system as a source of truth

We stopped designing with components that are ahead of the state of production and forced ourselves to be comfortable with code. To contribute to our design system, we now follow these steps:

Design systems are a team effort.

And, we hate to break it to you but it's likely never going to feel good enough! Embrace the true iterative nature of software design and development, and make a plan for how you can continue to iterate on your design system.

Theming principles we followed

Once starting this project, we quickly found there are a lot of resources out there about ‘do’s and don’ts for dark mode’, but one statement that stood out to me was:
“At higher levels of elevation, components express depth by displaying lighter surface colors” - material design
Dark Mode Principle 1: Higher elevation, lighter surface
In light mode, we often use drop shadows to show depth. In dark mode, drop shadows are not always the best approach. Imagine you have a light source on top of a table, all elements closer to you will look lighter and anything in the background will be darker. This also applies to UI design.
We took this rule and applied it to our ZenHub Board. As you can see below, the issues on our board are lighter in color than the pipelines, creating depth and hierarchy for the user.
Dark Mode Principle 2: Less saturated colors improve legibility and reduce visual vibration
When we were building out the new color scale, our visual designer created a spectrum of colors with shades in increments of lightness for each color in our brand. For example:

However, what we found worked for light mode, didn’t necessarily work for dark mode. This is because saturated colors in dark interfaces don’t pass WCAG's accessibility standard. Saturated colors produce optical vibrations against a dark background, which can induce eye strain – which is why we try not to use white text on black backgrounds. When designing for dark mode, modifying lightness in your color scale and reducing saturation will give you the best result.

In this example, our primaries (red and blue) had to be adjusted with a lighter shade to improve the legibility of the text and to pass the necessary contrast ratio. Less saturated colors from your color palette improve legibility and reduce visual vibration.

Developing for dark mode theming

In our design system, we have two layers of color variables: scales and themes.

Scales are where the raw color hex codes live. These values don’t change. Components won’t use these values directly, but the theme variables will point to them.

Themes are the stable API for components to consume. They are pointers to the scales, and represent a distinct functional value in the system.

Developers should be able to easily read the name of a variable and understand what it’s used for. Themes are managed via a specific set of theme variables that are swapped by simply changing a data attribute at the root of the application. Each set of variables is bound to a data-theme value which is applied at the app root, but could also support theming specific components as well.

All of the same variables but using different scale values

An example of scales:

Now that theming is involved. color-text-primary in:

The scale values never change, scale-grey-80 is the same in all themes. But the text color references a different grey variable in the dark theme.

Applied to our components:

Adding functional variables to Figma

We moved from designing with hex codes to only using functional variables that are aligned with our code base, making it easier for the whole team to understand. This saves the developers time during handoffs and limits the margin of error for inconsistencies.

This also meant that converting a page from light mode to dark mode took only seconds. Designers only design in one theme, light theme, and if we want to see what it will look like in dark mode, we just switch variants from day to night. That sure makes it seem easy, right?

Success metrics

We learned that about 20% of our user base had OS appearance set to dark before we launched. However, we saw a 36% of adoption in the first week of the release day. That meant that 16% of our users switched to dark mode regardless of their OS preference.

To wrap it up

Revamping our design system to make room for dark mode definitely taught our design team some hard lessons. The design team is now more involved in the development process and became familiar with the different libraries available in production. We reached parity between Figma and production, and built a consistent design system.

Ready to collaborate or just talk about design?

Connect with me

send me an email
or schedule a virtual coffee chat with me on calendly