A universal color tool for design systems.
White-labeling Design Systems for multiple brands with WCAG Color Contrast is a tedious and manual task. Despite many Color Tools available, nothing quite seems to fit the bill. This article describes Genome Color Tool, a web app developed to create brand-specific palettes for a variety of Color Systems.
Before diving in, “How should you name your colors in a Design System?” has helpful references to terminology and definitions. But, if you’re a TL;DR kinda person, please jump to Genome Color Tool and give it a whirl. This article will still be here.
In 2019, I was a part of a cross-disciplinary Spike Sprint to investigate cross-platform and cross-brand development for mobile apps. I was the iOS Developer/Designer on the project, and I called my part of the project Unified Design System Taxonomy.
A Design System can be standardized into a singular approach to providing cross-platform and cross-brand functionality.
I wrote two Sketch plugins. One generated tints/shades from specified colors with well-defined keys, which could be swapped for different values per brand. Another plugin exported colors and typography definitions into a JSON file from Sketch.
I exported four files, each themed for a different brand. I imported the JSON files into iOS and Android environments as resources where a platform-specific factory method would read and return the correct color/typography values to the system. With this approach, the app could theme itself automatically on build or via menu selection.
This approach was an effective (if primitive) implementation of Design Tokens, but I had never heard of tokens. Theo and Style-Dictionary would soon popularize the concept.
At the end of the Spike, we were able to present live demos, both Android and iOS, with four different themes — swappable at the touch of a button. Looking back, we could have done the same for the web, making a perfect trifecta.
However, I had a unique advantage.
I was the sole designer of mobile platforms, so I had control over the design and UI code for all brands. You might think Design Tokens drove the success of the project, but it was only a technical detail.
The success of the project relied on Standardized Naming Conventions because if four brands had different names for colors and typography, the JSON file would have been ineffective for white-label.
The benefit of Design Tokens was engineers didn’t have to manually enter hex codes, typography specifications, or re-build the app in different environments to apply themes. By using Standardized Naming Conventions, we made the developer handoff less error-prone and themes more dynamic with Design Tokens.
The Color Tool
This article is about the Genome Color Tool, inspired by solving one part of the Unified Design System Taxonomy Project (generating tints/shades). It defines a foundational piece of the puzzle of Design Systems for creating white-label Color Systems at scale.
A Color System is a set of defined colors — expanded into a group of tints and shades – which supports designers and engineers working with Design Systems.
Similar to a brand style guide, a Color System provides a wider tonal range to facilitate white-labeling, dark-mode, and WCAG color contrast compliance.
Several Color Systems are available, most custom-made for their own Design System. Material Design, IBM Carbon, SalesForce Lightning, and Ant Design are a few examples of Design Systems with their unique Color System implementation.
A Color Tool enables designers to create white-labeled, theme-able solutions for Color Systems at scale. They are essential when you’re designing for multiple brands. There are four main categories of Color Tools provided by Design Systems — “Limited,” “Unlimited,” “Opinionated,” and “Packaged”.
Limited Color Tools
Material Design and Ant Design offer Limited Color Tools, allowing the user to input a single color value to generate all tints/shades. This makes it easy to generate white-label themes, but this simplicity isn’t helpful if the brand is opinionated on specific tints/shades or needs WCAG color contrast.
Inputting a color will assign it to its base numeric weight, regardless of the weight/density of the color itself, making them non-opinionated for WCAG color contrast.
Unlimited Color Tools
These color tools are often associated with an existing Design System. Examples include ColorBox by Kevyn Arnott, Leonardo by Nate Baldwin of Adobe, and Primer Prism by GitHub.
They present an impressive array of 3D charts, graphs, sliders, and buttons for fine-grain control over hue, saturation, brightness, easing curves, and the number of steps to generate. They are amazing, yet I’ve never had any success with them.
Giving an infinite amount of control seems a good idea, but it often overwhelms and pushes the responsibility of understanding to the designer. Unlimited Color Tools often tell users what they could do but never what they should.
Opinionated Color Tools
On the other hand, some Color Tools are highly opinionated about WCAG color contrast. One example is AccessiblePalette by Eugene Fedorenko.
Unfortunately, AccessiblePalette doesn’t provide a way to download results for designers or engineers, but it certainly represents a step in the right direction.
Color Systems such as IBM Carbon and Lightning SalesForce do not offer a Color Tool. If you decide on either of these two systems, white-labeling becomes challenging to say the least. However, these systems are highly opinionated on WCAG color contrast which is exactly what we want to achieve.
Instead, a Packaged Color System offers a large collection of colors, each hand-tweaked to meaningfully weighted standards for WCAG color contrast. This is great, but the problem is they are never the colors of your brand. To reproduce this functionality requires a lot of knowledge and a considerable amount of effort.
This is feasible if you have the knowledge, the time, and a single brand. But if you’re designing for white-label for 3, 6, 12 brands or more, it becomes exponentially difficult and error-prone.
Opinionated Color Systems depend on CIELAB to create standardized color weights for WCAG contrast. CIELAB is a device-independent color model used to measure color accuracy and transformations from one color space to another.
CIELAB defines color in a three-dimensional space. L* indicates lightness, and a* and b* are chromaticity coordinates. a* and b* are color directions: +a* is the red axis, -a’ is the green axis, +b* is the yellow axis, and -b* is the blue axis.
- L*: Lightness
- a*: Red/Green Value
- b*: Blue/Yellow Value
The a* and b* represent the chromaticity of the color, but Opinionated Color Systems are only concerned with the L*, which is the color’s Lightness or ‘density’. The L* scale proceeds from 100 (white) to 0 (black).
If you know WCAG color contrast, the ratios of 3:1, 4.5:1, and 7:1 are familiar. However, if you consider WCAG defines the difference between white and black as a 21:1 ratio, it may leave you wondering what 3:1, 4.5:1, and 7:1 exactly mean.
Color science is complicated. Simply put, the WCAG ratio is calculated by removing the 2.2 gamma curve of the sRGB color space, making all values linear.
It may surprise you to know that the mid-tone 50% gray you perceive is only reflecting (approx) 20% of light. Human eyes logarithmically ‘curve’ the 20% to a perception of 50%. Think of it as a highly automated camera aperture.
The advantage of removing the 22% curve for WCAG is that it creates a stable reference to calculate a distance (a ratio) from one density to another.
Removing the gamma curve is an effective strategy, but it does create a UX complexity. Rather than being naturally understandable, WCAG ratios appear ‘magical’ and non-intuitive to users.
Rather than removing the gamma curve, CIELAB normalizes it into the L* value to closely match human perception. With CIELAB, we see that a 4.5:1 ratio equals L*50, which is between 0 and 100, or a mid-tone value. Likewise, a 3:1 ratio is L*60, and a 7:1 is L*40 (on white). Instead of ‘magical ratios,’ CIELAB makes the perceptual meaning more intuitive for the user.
Simply put, when setting typography of any color on a white background, WCAG says the type should be a mid-tone value or darker. If the background is black, choose a mid-tone value or lighter. The color doesn’t matter, but the density does.
Genome starts with a non-optimized Color System. Each step is L*5 distance away from the next (I added L*97.5, between L*100 and L*95, because it is commonly used in designs). Therefore, the non-optimized base is 20 tints/shades plus black and white, for a total of 22.
A non-optimized color system of 22 tints/shades is far too many to be useful for designers (i.e., Hicks Law), which is why it needs to be optimized to a more reasonable amount — closer to 10 steps.
Optimization is the process of removing approximately 50% of the non-optimized colors. This is essential for creating a Color System that does not overwhelm Designers and Engineers with color options.
Visualizing the differences between various Color Systems, we see obvious disparity in L* values represented. Each Color System has advantages and disadvantages, yet there are similarities between Carbon and Lightning worth noting.
For highlights, 1/4 tones, and mid-tones, Carbon, and Salesforce align on L*95, 90, 80, and 60. I see those densities as indispensable for paperwhites, separator lines, text field borders, and disabled controls.
For 3/4 tones and shadows, Salesforce Lightning chooses L*20–15–10, and I wholeheartedly agree, especially for chromatic colors. IBM Carbon, on the other hand, uses L*25–15–5, but I find chromatic colors on L*5 lose saturation and are practically indistinguishable from black, making it a less-than-useful color.
The best optimization for the organization can only be determined by the designer, but the Genome Color Tool makes it easy to see optimizations that major companies thought were best for them. Additionally, it offers a custom-made Genome Color System optimization which may be of interest.
To make white-labeling effortless, the designer wants to standardize on one optimization which works best with all brands/products of their organization. Keep in mind new brands/products will inevitably be added in the future, so the designer’s choice is critical to scalability.
In non-optimized mode, users enter hex codes. Each entry is placed in the nearest L*5 slot available per column. Genome calculates the best possible tints/shades while preserving saturation.
Users may choose from several optimizations to preview. The ‘Download’ button saves a JSON file that can be imported into Figma via a plug-in using any optimization (including non-optimized).
Genome recognizes two different user choices. Base Colors are the users’ first choice and the most important. Additional colors are Pinned Colors and are given a lower priority for optimization placement.
⭐️ Base Colors
Base Colors are prefixed with a “⭐️” emoji to indicate it is the user’s first and most important choice. Typically, the choice is a mid-tone value, but Genome recognizes any value.
Each column has one Base Color, which Genome uses to generate the initial set of tints and shades.
Because Base Colors are the most important, they have first priority and are always present in the chosen Optimized Color System scale even if it’s not an exact fit for that system.
Pinned Colors are prefixed with a “📍” to indicate additional colors have been inserted into the scale. Pinned Colors are accessible with the ‘+’ button next to the base color input field, which presents a modal dialog to enter additional colors.
Where brands have defined multiple shades of the same hue (i.e. blue, bright-blue, light-blue, dark-blue, deep-blue, etc.), designers will find it valuable to combine them into a singular semantic column.
Pinned colors adjust the hue of steps between Base & Pinned Colors as the scale travels to lighter tints and darker shades. This gives a comparable functionality to “Unlimited” Color Tools but is much simpler to use.
Unlike Base Colors, Pinned Colors are a lower priority and may overwrite other pinned colors when Optimized into a particular Color System. However, Pinned Colors are not allowed to overwrite the “⭐️ Base Colors”.
Genome presents ten semantically named columns that designers can change to any name they prefer. The default values are primary, secondary, tertiary, positive, negative, highlight, attention, info, system, and neutral.
Standardization is indispensable for scalability, so I recommend semantic names that describe the intention of the color rather than definitive names that describe the color itself. All apps have a Primary color, but not all apps have “Cornflower Blue”.
Genome does not offer contextual names. However, knowing the difference between Semantic-Weighted and Contextual naming conventions is important. For example, the Semantic-Weighted name of color-primary-400 describes the intention (semantic) and density (weight) but isn’t specific to how it is used.
A Contextual name, on the other hand, specifies colors in the context of specific components, pseudo-states, and dark mode.
Including Contextual names in Genome is possible. However, much like Definitive Names, any naming convention for Contextual would not align with what your organization currently uses. A project for another day!
WCAG Color Contrast
It is difficult to visualize which colors pass to other colors, but Genome has a feature to make it easier.
When hovering over a color, the user may press the ‘3’ key and see which swatches pass for 3:1 ratios. The ‘4’ key shows 4.5:1 ratios, and the ‘7’ key presents 7:1 ratios.
Users tend to think of larger numbers as darker values, but the CIELAB L* value goes the opposite direction (larger numbers mean lighter values). Color weights are an abstraction of the L* to provide a more intuitive experience for the user.
Today, there is no consensus on how to name colors, typography, spacing, or anything else. This causes a lot of inefficiencies as we see new Design Systems being created on a daily basis, each introducing its own unique standard.
The only color system that directly uses L* values for weights is Lightning SalesForce.
The Genome Color Tool uses chroma-js as its primary color engine and Oklab color space as the color model. Oklab is based on CIELAB but renders color better, especially in blues.
Rather than directly scaling from one color to the next, Genome generates a large array of ‘candidate’ values and finds the closest match to the desired non-optimized L* target. It took me a while to realize transitioning a chromatic color such as blue to a neutral black/white naturally desaturates the color as it moves closer to those end-points.
I hope you find Genome Color Tool useful when setting up your design system for white-label and dark-mode functionality. As designers, it’s not a task we do every day, but having a tool available when you need it is nice. I expect to add more optimizations in the future and improve the UX over time.