Designing Hazel’s Accessible Color System (Part 1)

What happens when your simple color palette also needs to accommodate interaction states, sentiment, accessibility requirements, and more?

Francis Wu
5 min readMar 21, 2022

There’s no shortage of articles and videos about designing UI color palettes. You can even use a tool such as Material Design’s Color Tool to create an exhaustive set of harmonious colors.

But when it came to Hazel’s design system, I thought selecting its colors should also be… systematic. I don’t have the confidence to pull the right colors out of thin air like a Sorting Hat at Hogwarts. Colors should have meaningful relationships between them that could be codified.

It knew going in this wasn’t going to be easy. Brand guidelines, interaction states, sentiment, and accessibility requirements are only some of the elements that can contribute to the complexity of a color system.

In this 2-part post I’ll walk you through my journey to creating such a color system. And hopefully, you’ll walk away with something that you can apply to your own.

How have others done this?

I looked around for a thoughtful way to approach colors and Shopify’s color system came out on top. The fact that they made their colors and components available as Figma community files certainly didn’t hurt.

Polaris’ color palette

Upon closer inspection, the way it was organized raised some questions. Isn’t “Background” just another set of surfaces? Why “Text On” and “Icon On”? Aren’t all text and icons on something already? Isn’t “Focused” just another border? Aren’t “Interactive” and “Actions” a little redundant?

But I had a growing list of components and variants that needed colors and I now have something to work with. I’ll figure it out as a I progress. #yolo

Getting the base colors down was simple enough.

Base colors


For surfaces, I made a few tweaks. I included backgrounds (“canvas”) and inverse surfaces — such as for toasts. There was also an “admin” surface color to be applied to the app bar for “admin” users. You can start seeing interaction states colors as well.

Base surface colors included backgrounds, inverse, and admin

Then there were the sentiment surface colors, useful for components like alerts and tags.

Sentiment surface colors

There were other surfaces as well, such as selected surfaces and the scrim. Scrims are those semi-transparent backdrops against which dialogs rest.

Selected and scrim surfaces

And that’s it for surfaces. So far so good!


For content and icons, I decided that if it rests against a surface, it’s all content. Easy peasy.

First, the neutral content colors.

Neutral content colors

Then the sentiment content colors, which are useful for buttons and icons.

Sentiment content colors
Sentiment content colors applied to buttons and icons in alerts

Lastly, there were selected content colors. These appear in places like the nav drawer.

Selected content colors
Selected content colors in the nav drawer


Border were as simple as content colors. First, there was a border to divide all the things.

All purpose border color

Of course, there were sentiment border colors, which appear in alerts.

Sentiment border colors

And then there are focus border colors, which are useful for interactive elements such as buttons and input fields.

Focus border colors

A Note on Opacity

You’ll notice that a lot of these colors aren’t flat. This is because there are going to be scenarios where the application of flat colors to UI elements will lead to undesirable results. This is especially true in interaction design.

Consider the following dropdown menu of fruits with badge counters. Pretty innocuous, right?

Dropdown menu of fruits

What if this was a multi-select menu and one of its items was selected? And what if you were mousing over the menu?

Flat colors lead to loss of contrast.

If the badges were a flat grey, you’d notice how the badges just blend with their surroundings. Contrast is lost.

But if the badges were a transparent grey, contrast is automatically kept.

Transparent colors maintain adequate contrast.

Here are the flat and transparent colors side by side, for comparison’s sake.

Flat and transparent colors compared

By using transparent colors, you’re automatically ensuring a visual relationship between layers of UI elements.

Sure, you can establish additional flat colors to cover this scenario. Or you can create an exception here and make all badges transparent. But this path leads to death by a thousand cuts.

Speaking of which…

Going Off the Rails

Looking at Shopify’s colors, I took “interactive” and “actions” to mean “components”. Because I don’t know. Don’t ask. ;)

I lifted up my sleeves and created a palette of colors for all my components. And I ended up with this little monster.

206 colors and growing

Aw shit, 206 colors for only 8 components. And more were coming.

Today, our design system comprises of ~90 components and God knows how many variants. Creating design tokens out of these was going to suck!

By this point I was seeing colors that weren’t there and I had to sleep on it.

Continue to part 2, where Asana breaks this case wide open!



Francis Wu

9 parts dad. 7 parts designer. 5 parts developer. 3 parts product manager. Some parts private.