We've already covered the theory behind our semantic color system as well as how it works for designers. This post covers how it works when the rubber hits the road: In code!
We believe that a design system isn’t worth much if it’s only used by designers. So when we started working on this new approach to colors, we knew we wanted to make it simple and usable for developers, too.
So we built a Figma integration that takes all of the color information from our color file and outputs usable code (special thanks/shoutout to Kyle Robinson Young on the YNAB development team, who helped build the integration).
YNAB offers an iOS app, an Android app, and a web app. We rely on our design system to keep things consistent between each platform, so the integration outputs code for each platform.
Each platform has some idiosyncrasies as far as how colors are defined and how light/dark mode switching happens, so we’ll run through each of them.
iOS
For iOS, the integration outputs a color file that is broken into two sections. This is where all of our iOS app's colors are defined.
The first section of the file defines the palette colors. These are private because we never refer to them directly — instead, we refer to semantic colors. This keeps things consistent and guarantees that they look good in light and dark mode.
In the next section of the file, we have our semantic color definitions. These are what actually we use to apply color. Each and every semantic color points at a palette color for light mode and for dark mode.
One of our iOS developers wrote a simple function, that looks at the user’s display mode and determines which color variant to display. That way, things will “just work” between modes. We also built in a safe fallback, in case users aren’t running iOS 13 yet.
We use the description field of the semantic colors from Figma to populate the proper references to the base palette for each semantic color.
Android
For Android, the integration outputs to three color-related files.
First, there’s palette.xml
. This is the base color palette where all possible colors are defined.
Next, there’s colors.xml
and colors.xml (night)
. These each have each semantic color listed, with the proper reference to the base palette for each mode — light mode definitions go in palette.xml and dark mode definitions go in colors.xml (night)
.
When we’re applying colors, we simply refer to colors defined in colors.xml
and the right variant renders based on the user’s mode.
Web
We use Stylus for our web app, so we output a palette.styl,
colors.styl
, and dark-theme.styl
file.
As you can probably anticipate from the structure of iOS and Android, palette.styl
contains the base palette colors. ‘Colors.styland ‘dark-mode.styl
contain CSS variable definitions that reference the proper base palette colors.
So when we are applying colors, we use the CSS variables we define in colors.styl
and dark-mode.styl
and render the right variant based on the mode the user has selected.
We haven’t released dark mode for the web, so this approach is still experimental, but we’re confident it will work just as well as the system has been working for iOS and Android.
Communication between designers and developers
The fact that we output color definitions directly from Figma means that when a developer looks at a design, they can use the exact same name as the designer and the code will “just work.”
The Figma integration makes it easy and lightweight to keep the system up-to-date; relying on manual updates and communication for a system like this would be a surefire way for it to quickly get out-of-date, messy, and to start to diverge between different platforms.
With this system, we simply run the integration any time colors change in Figma (which is our “source of truth” for all things color). Then developers immediately get access to the latest and greatest colors.
But the technical specificities here are less important than the fact that the philosophy and the language around colors are shared between designers and developers. This system gives us a shared language for talking about colors, and empowers everyone on the team to pick the right color for the job.
Questions? Comments? Get in touch!
That’s all for our series on how we built a semantic color system for designers and developers at YNAB! Feel free to reach out if you have any questions or suggestions. Our hope is that this system can be as useful to other teams as it has been to us!
Top comments (4)
Hi Emily.
First of all, thanks a lot for sharing your insights. This is exactly the same process I am building up. In my opinion this process is inevitable for every Team out there. Automation is the step needed to assure focus on product development, rather then trying to fix everything manually (inconsistent design over all platforms ugh).
I would love to be an early adopter of “semantic color updater” plugin as well as the Figma integration that outputs code. My heart is beating for awesome stuff.
Keep up the great work!
Sorry Emily, it's unclear from your post that the script that generates though Android, iOS and Web resource files is provided by Figma out of the box or sth written in house by you?
If it is written by you, can it be open-sourced and shared with us? :D
Hey Emily,
thank you for your series once again. It helped me to develop theemo and ember-theemo. I wrote two articles about it (afaik YNAB also uses ember), so this might be of interest:
Let me know. I am happy to collaborate on this.
gossi
Hi and thanks for writing this, it helps alot in process :)
I have a question regarding having multiple brands in the same palette.style and each brand having a (primary) or brand color, how whould you name them or handle it?
Thanks // Emil