The design team at Novoda has been dabbling with Design Systems in Sketch lately. Design Systems work as a unique source of truth for every imaginable component of an app’s interface and are quickly becoming an essential part of UI design as they allow easy management and maintainability of design files that inherit from it.

We’ve been learning as we go, and we absolutely love them. Over the course of a few months, as we’ve been building design systems, we made sure to document our findings internally. In this blog post, I’m going to share how we organise and manage icons in a design system to help make your design process more efficient.

Free tip of the day: The secret is to think like a developer!

First things first, what’s the problem?

A Design System should be built with reusability and adaptability in mind—that’s its purpose in the first place. In retrospective, this is exactly what I completely disregarded when I started adding icons into the design system I was building, much to my surprise. I started with a simple shape in an artboard, and a colour override on top, so I could change its colour on the fly.

I ended up using this method for most of my icons, but I was slowly starting to realise that it was becoming increasingly difficult to handle multiple sizes, multiple layering, exportability and even cases where the same shape was used for different icons but in different orientations (such as arrows). A lot of problems started to surface, and a sense of tech-debt was creeping behind me.

‘Special cases’ were required every time I had to use an icon that we already had but in a bigger size. They would fail to appear on Sketch’s override menu too, which would result in more work.
Zeplin only picks up the defined specs of a symbol, so that if you change its size or contents dynamically through the override menu, Zeplin disregards that and the export turns out to be all wrong.
A lot of ambiguity was introduced when the burden of choosing the right icon was left up to symbols housing those icons, as we wouldn’t have clearly defined styles.

Here’s what we came up with…

High-level solution

Before diving into specifics, let’s first get an idea of what exactly it is that we’re doing. When you’re working with a design system, cases where you’ll have to use a standalone icon will be pretty rare. That is because, ideally, the system will already include a component that houses an icon, so you will only need to change the icon through the override menu.

What we want to achieve is to have a way to build icons but also edit them easily if we need to, while also simplifying our workflow when we use them in our design files.

The system’s breakdown might go a little bit like this:
Starting from the smallest components and going up to the biggest, there’s Colour symbols, Icon symbols, Text symbols, Components that combine all of the previous, and maybe a sticker sheet where components themselves are combined. When you paste from the sticker sheet to your design file, all components will remain linked to the Design System.

Now, we’re focusing on a low-level element, namely the Icon symbols. We’ll break them down into 3 parts:

  1. Raw elements, which will be the source of truth
  2. Templates, where sources get combined
  3. Final icons, where templates are used to create every icon in the icon set

1 — Have a single source of truth for every shape

Every icon shape should be its own symbol, with a colour override on top. Doing that is simple; turn your shape into a mask and place a colour symbol on top, aka an override. The colour override symbol can be a single colour, a gradient, or even your own arrangement of multiple layers. This icon symbol will be the single source of truth for that shape. Use a consistent size for these, something like 24x24 pt. Remove the fill from the shapes so that the colour override doesn't clash with the shape's colour when there is some transparency.

Any sort of decorations, such as a circle background that goes behind a shape, should be a standalone symbol as well because even decorations deserve their own source of truth.

If you have identical shapes but with different orientations (such as a thumb up and a thumb down), keep only one of them as the source of truth. This is so that when you need to edit the shape, all icons of that shape will be updated too.

Since these are the most low-level building blocks of the icons, editing these shapes will affect all other symbols which they are linked to.


2 — Introduce templates

This is where we assemble the types of icons. Are your icons 24x24 pt? Make a template of that, and throw one of the icons inside. Do you have some icons that have a background circle? Make a new template that includes the circle and an icon on top. Are some of your icons 72x72 pt? Hell, make a template for that too. Don’t be afraid to use templates inside templates if you need to.

The way this benefits us is that we’ll have clearly defined styles for every type of icon, so we never need to assemble icons on the fly, or remember the exact specifications for a style. It will also give you a good idea of the different styles of icons you use in your product!


3 — Use the templates to create every possible icon

Now that the templates are ready, use them to create every icon in the icon set. For example, if you have four icons that use the 'Icon on Circle’ template, make a symbol for each one of them using the template as a base. Now, lock the template layer inside, and make that symbol exportable. In this way, you’re securing the final appearance of the icon and making it ready to be used by developers exactly in the way they would need to. The icons in the system will reflect perfectly the icons in the code repository.


Finally, all you have to do is use the highest level icon (step 3) in your symbols, and everything will work perfectly. Zeplin will work flawlessly, the developers will love you, and you will save yourself a lot of headaches.