Building a Design System in Figma

A quick-start guide, with Auto layout and Variants

Apart from being one of the most talked about topic in the design field, the rising need for design systems could be attributed to the following goals:

  • Provide consistent user experiences

Recently, Nielsen Norman Group published an article about the pros and cons of implementing a design system. Of all the points raised, this is what resonated with me the most:

Teams can continue to use the same elements over and over, reducing the need to reinvent the wheel and thus risking unintended inconsistency.

— Therese Fessenden (NN/g)

I experienced a design inconsistency problem while working with an existing color palette. I was trying to find the “right” shade of green for a new button, and this color was supposed to work with the existing palette. I spent a whole afternoon trying out different shades of green and eventually ended up with a blue. This wasn’t sustainable for a start-up that was trying to deliver a feature as fast as possible. In order to avoid this situation, I decided to create a design system for colors when I started working on another project called Goody app.

I’ve been working on a website for a start-up digital consultancy. Let me share how I have been building a design system in Figma. Auto layout and variants were applied to the most recent iterations.

Exploration

Wireframes

After creating a set of wireframes, I got an overview of the pages that I need to work on and the elements that I need to include.

  • Home Page
Wireframes for website project

Style Guide:

Color Palette

When you create a new team in Figma, it comes with an existing design system project, and inside is a default file with ‘Color Styles’. This is a great place to start exploring and tinkering with an actual design system, and it’s quite fun! However, when trying to work with an existing color palette, it’s good to start in a spreadsheet before implementing the color palette in Figma.

In this case, I started with a primary and secondary color, I generated a color palette using Material Design Color system tool to provide colors that meet accessibility standards. I transferred the set of HEX values into a spreadsheet, then manually checked the contrast ratio between background and foreground by using WebAIM’s contrast checker tool. From here, I was able to determine which color are suitable to use against white or black texts.

When comparing contrast ratios, I found that the numerical results cannot be the only deciding factor. Sometimes, checking visually made more sense than relying on numbers.

Generated colors in an Excel sheet

For starters, the contrast ratio has to be at least 3:1 for large texts and 4.5:1 for normal texts to pass WCAG 2.0 AA level. Let’s take an example, Purple 400 / 8057ff has a contrast ratio of 4.72:1 with black text and 4.44:1 when compared with white text. By testing it visually, it is more readable as a background color for white text. Hence, I decided to classify Purple 400 / 8057ff to be used with light-colored texts such as white.

Before going implementing the palette in Figma, I was inspired by an article that showed how to quickly set up a color system in Figma. After settling down with a naming convention, I was able to generate the color chip labels using a plugin called: Smart Text. By selecting ‘Fill Color’ and the ‘Layer Name’, it generated the corresponding HEX values and the corresponding naming conventions.

Generated colors in Figma

To generate these as Colors Styles in this Figma file, I used this plugin: Chroma Color. Under ‘Assets’, I published these Color Styles so that they could be used across the whole project. I went through a process of adding and editing color chips as I worked through the style guide. The plugins made it easier to edit and generate new names for each color chip, especially in batches.

Typography

By the time I was exploring type sizes and weights, I applied these color styles to backgrounds and texts. There were several iterations using Helvetica, I recently updated it by applying Figma Variants.

One dilemma was to either combine all the types into one set of variants or to categorize them. Combining all of these types will show everything in one list — this seemed to offer flexibility. On the other hand, categorizing would literally provide a “system” with some constraints. For example, all types under Headers would be found under Headers, and not in Subheaders, nor in Texts.

Typography, with Variants

Arguably, you can select any type when designing and interchange the Variants as needed. In this project, the mentioned constraints were implemented to give a sense of structure and organization.

The typography was classified into 3 main categories:

  • Header (Header Light Mode, Header Dark Mode)

Naming convention: Variant Name/Type/State

Example: Subheaders Light Mode/Subheader 1 16px/Active

Subheader, with Variants

Components:

List of Atomic Components

I initially grouped and identified the main components as the following:

  • CTA (Primary Buttons, Secondary Buttons, Text links Navigation, Text links Defaut, Text links Highlighted)

As I went through iterations, I realized that it’s hard to group buttons and text links into one Variant based on how they are used. For example, the most critical property to be shown for the text links are the text sizes. With buttons, the focus is more on the sizes of the buttons, and if it had an icon or not.

First iteration of Buttons, without Variants

Hence, I decided to break down the ‘CTA’ components into ‘Buttons’ and ‘Links’. ‘Text links Navigation’ and ‘Text links Default’ turned out to be the same thing with similar behavior, only the text size differed.

Second iteration:

  • Buttons

Buttons:

Variant property setting: Variant Name/Type/Format/State/Size

Example: Buttons/Primary/No-icon/Active/Small

Second iteration of Buttons, with Variants

Links:

Variant property setting: Variant Name/Type/Format/State/Size

Example: Links/Secondary Link 16px/Highlighted/Active/Small

Links with Variants

Form fields:

For the Form fields, I focused on the states. I identified 2 critical properties:

  • Empty Format

I then used Variants to further categorize the other components:

Variant property setting: Variant Name/Type/Format/State

Example: Form Field/Phone Number/Empty/Error

First iteration of Form fields
Second iteration of Form fields

Tooltips:

I decided to create another set of Variants for the Tooltips to better manage and incorporate them to other components in the design system.

Variant property setting: Variant Name/Type/State

Example: Tooltip/Light/Active

Tooltips, with Variants

Alerts:

At first, I combined all Alert components. Although they are all alerts, the ‘Alert Messages’ did not function the same way as the ‘Alert Headlines’. So I regrouped based on their how they are used. Alert messages are in-line texts that could be found in the Form fields, while Alert banners could be found on top of a user screen.

Variant property setting: Variant Name/Type/State

Examples:

  • Alert Messages/Alert 3 20px/Active
First iteration of Alerts
Second iteration of Alert Messages, with Variants
Second iteration of Alert Banners, with Variants

Icons

I used open-source icons from feathericons.com.

Icons from feathericons.com

Complex Components

I applied Auto layout to the simpler components before applying it to more complex ones, termed as “Organisms” based on Brad Frost’s Atomic Design approach.

By using aspect ratio tools from Vitalii and Abel Hancock, a Card or a Dialog from this design system could be resized without the need to constantly resize the attached image.

List of Organism Components

  • Navigation

Navigation:

Variant property setting: Variant Name/Type/Format

Example: Navigation/Horizontal/Expanded

Navigations, with Variants
Horizontal Navigation, with Auto layout
Vertical Navigation, with Auto layout

Cards:

Variant property setting: Variant Name/Type/State/Size

Example: Card/Horizontal/Active/Large

Cards, with Variants. Credits to Jignesh Gajjar for the image from LottieFiles plugin
Horizontal Card, with Auto layout and Aspect Ratio tool
Vertical Card, with Auto layout and Aspect Ratio tool

Dialogs:

Variant property setting: Variant Name/Format/Size

Example: Dialogs/Form/Small

Dialogs, with Variants
Small Dialog, with Auto layout
Small Information Dialog, with Auto layout and Aspect Ratio tool

Design Codes

The CSS codes are automatically generated under ‘Inspect’ tab in Figma as you design. If I’m not mistaken, these Inspect codes are only editable to owners or contributors. Here’s a peek at how codes are presented in Figma for a button:

Layers in Figma for a button
CSS codes when selecting ‘Primary/ No-icon/Active/ Small’ button
CSS code when selecting ‘Text 3' layer

From here, I visited w3schools.com to get a CSS Button html code, I retained the 3rd button from the list and retrofitted it to the button design:

Code: <button class=“button”>Send Message</button>

html code from w3schools.com for buttons

I edited and explored until I recreated this button in an html file. I realized that it’s not an instant handoff, where anyone could just literally select a button and copy paste the codes in one go (To coders: Correct me if I am wrong). It took me awhile to discover that I had to select several frames to get the codes that needed to be combined and formatted to work.

Sample retrofitted CSS codes via Atom for ‘Primary/ No-icon/Active/ Small’ button

For example, if I only select a button (Primary/No-icon/Active/Small), the codes under ‘Text 3’ will not be shown until I further click and select ‘Text 3’.

Here’s how it looks like in html, including the codes under ‘Text 3’:

Learnings

Thinking back, I spent a considerable amount of time picking a naming convention for each of the components, and it initially felt like it slowed me down. However, I found that naming and grouping is one of the most important things to decide on before working on the visual elements. By sticking with the naming conventions, awkward names were prevented, it also became apparent to me which components were still missing.

I keep a list of the naming conventions in an Excel sheet, it may appear like a redundant work, but it was helpful when I was cross-checking the consistency of the names. One example is with the Form fields, I used both ‘Phone’ and ‘Phone Number’ in Figma, where in fact they referred to the same element. This is a perfect example of how an error could easily cause inconsistencies and confusion to design system users.

Naming components in an Excel sheet

Moving forward, I’m still exploring if I need to use design system documentation tools like zeroheight, given that my current coding skills are limited.

It did took quite some time for me to explore and understand how aspect ratio tools work in Figma. For this matter, Material Design and Atlassian were also some great sources of inspiration.

Figma Auto layout and Variants are customizable in a sense that you can create constraints and flexibility as needed. It has enabled me to weigh in different pros and cons of my design decisions. But more importantly, it has helped me confront if those decisions would be sustainable.

Reflection about design systems

Kick-starting a design system empowered me early on to create different ways of designing. It has allowed me to fix unforeseen issues like a missing component state/format. This would reduce unnecessary workload and even panic in a team.

Therese Fessenden from Nielsen Norman Group writes,

When poorly implemented and maintained, design systems can become unwieldly collections of components and code; but, when implemented well, they can educate team members, streamline work, and enable designers to tackle complex UX problems.

A design system is there to act as a guide for a team, it shouldn’t be followed without question. It should also continually evolve together with the product involved.

If you own or feed into a design system. Make sure there’s a sense of openness to change. Be okay to give openness to feedback higher prominence. And show how things are in a state of development ... It’s created and improved by any and every team that uses it. — Andrew Duckworth

With all the hype around design systems, it’s easy to lose track as to why or why we do not need to build one. It’s important to consider that building a design system requires investing time and effort.

Pascal Barry shares how design systems are a waste of time, it is also a single point of failure if it causes an error across all interfaces, and since it’s harder to debug than to deploy, the only solution is for developers to invest more effort in testing and maintaining it. He also argues that designers should focus on more important problems:

Users don’t care if every border-radius on your buttons is the same. They will, on the other hand, quickly ditch your product if you’ve failed to resolve core interaction problems.

Interestingly, Yesenia Perez-Cruz from Shopify writes:

The moral is: investing in infrastructure is worth it, if the benefit to people is worth the cost of maintaining the infrastructure. Ultimately, like paved roads, we create design systems because we want to help users accomplish tasks more easily. We lose sight of this when we focus too narrowly on design systems as a tool that helps internal teams move faster. A design system that allows you to efficiently ship a confusing user experience has no value.

It would be interesting to further find out how this design system project could be improved. Also, I have yet to write about the rarely discussed hurdles that arise from design systems, especially when working in a team, stay tuned.

You can view the design system contents here.

Thanks for reading! Feel free to comment or say hi 💗

UX Designer. Visit me at www.checkeredpotato.com