How I automated the process of generating color themes
Context
At Swiftly I design white-label web and mobile tools for retailers. The products are designed so that customers can customize the colors and graphic assets to match their company’s brand and obtain an intuitive and attractive interface. As such, we face the unique challenge of creating a consistent user interface with a constraint, that the color palette for each of our clients will be different.
Problem statement
Each element in the user interface has an assigned color style, and to re-skin the UI, we must update all the colors assigned to color styles. For each client, we did this manually to ensure an accurate and accessible result. But this approach was inefficient and highly error-prone due to the repetitiveness and volume of work required to update all the colors for both light and dark themes and to test them.
Thus, I decided to take a programmatic approach.
Color patterns
To determine whether or not this process can be automated, I began by researching the logic behind the colors used in our UI. Taking the most diverse color themes that we had at the time, I manually compared all colors in these themes. Next, I exported all colors in CSV format to identify patterns and sorted and grouped them based on different parameters.
I found that each app had one to three basic colors and that all the other colors were simply variations of the basic colors. Moreover, all non-basic colors were generated by the same logic for every theme.
To verify the logic, I manually recreated some of the themes using Adobe Color Wheel, and, to my surprise, it worked pretty well.
This small experiment helped me verify the logic and find additional variables and constraints.
Color spaces
Suddenly, I faced a huge issue. With Adobe Color Wheel or other popular color conversion tools results were highly unpredictable in terms of accessibility and contrast ratio.
There were some requirements for an accent color in our system. We used the accent color to replace the primary color in some cases, so we needed them to have similar perceptual brightness. Additionally, the accent color was by default the opposite (complimentary) of the primary color.
Here was what happened when I took a yellow color as a primary one. The yellow color #FFFF00 (60 H, 100 S, 100 B) had a contrast ratio of 19.56, while its suggested complementary blue color #0000FF (240 H, 100 S, 100 B) had a contrast ratio of 2.44. There was only a change in hue, but the colors had a completely different perceptual luminance, so we couldn’t use them as a pair.
There was a problem with the color space used by most color conversion tools. The RGB color space (or its variation HSB) does not respect human perception of brightness and contrast.
I was not the first one who faced this problem, and after some research, I learned that the proper way to solve this issue was using LCH color space. You can read about color spaces in the insightful articles by Evil Martians or Eugene Fedorenko.
My testing of the LCH color space with a color converter created by Evil Martians found that it worked quite well for us. Hence, after gathering all the logic from the previous steps and resolving the issue with color brightness, I proceeded to prototype a tool for generating color themes.
Prototype
I found chroma.js, an amazingly simple JavaScript library for all kinds of color conversions. I created a prototype after working with it for a few hours. This prototype takes one to three colors as input and generates the entire color palette while providing an accessibility check simultaneously.
Here is a public version of this prototype with a standardized color palette.
Give it a try!
Figma plugin
Having created a functional prototype, I built a Figma plugin. I found a handy template for creating Figma plugins by Thomas Lowry with all the necessary components in the Figma style. Thus, with the help of this template, my own prototype, Figma’s API, and StackOverflow, I built the first version of the plugin.
After adding additional settings and a mode switcher, I tested the results on some clients. Although I had to correct colors manually in some cases, this was a significant improvement compared to our 100% manual approach.
I showed it to the engineering team, who suggested adding a feature to export color styles. Using it, we were able to improve the design process and leverage the plugin to help engineers and the QA team in re-skining and testing the product.
I also added several new features, including saving color themes, publishing them in a team library, and even creating an API.
With my continued improvements, the plugin has already become an everyday tool for our team, and has improved our workflow significantly.
“The tool that Andrei has created allows the full product & Engineering team to express endless brands on our platform, without sacrificing good color practice such as accessibility standards and effective UX color communication. What once was a month long challenge to balance a brand’s style guide to our platform became an instant plug-and-play activity possible in moments.”
Emily Corace,Design Director
Final remarks
As a product grows, the complexity of a design system increases. Before, color themes could be created manually, but this added complexity created the potential for human error. Even without errors, such a manual process was highly inefficient. Moreover, a design system used at scale can compound even the smallest errors and negatively affect the user experience. By automating the design process, we can create high-quality assets that are well-tested and ready for production.
While working on this project, I discovered that the LCH color space is superior to old-school RGB. Moreover, chroma.js provides a very reliable color conversion tool, and the Figma documentation is relatively easy to follow.
By automating the generation of color themes, I could avoid human error and save considerable time on manual work and accessibility checks.
In addition to the original version, I created a simplified community version (the original has some settings and features specific to our product). Feel free to try it!
I want to thank my colleagues Emily Corace, Nikita Danchenko, Andre Marante, and Hasan Edain for their support throughout the process.