Creating themeable design systems

Kolby Sisk
UX Collective
Published in
8 min readFeb 26, 2020

--

Creating themeable design systems

Themeability is a largely overlooked feature when creating a design system. That’s an unfortunate fact as retroactively adding themeability is an arduous process. Themeability is a complex feature in that it requires forethought when architecting the design library, and the coded component library — but more-so — because it takes a bit of orchestrating between the two to get it just right.

What is themeability?

Themeability is a feature of design that allows you to easily change the look and feel throughout the entirety of a design, or design system.

  • Dark mode
  • Product specific look and feel
  • White labeling
  • Wireframe components to design with
  • Marketing look and feel

Those are all examples of problems a theme can solve. Often, a separate design system — coined a local design system by Spotify Design — is created to deal with this splintering of essential UI aesthetics. Most likely a new design system is overkill and all you really need is a new theme. However, this requires an engineered solution that’s able to apply the theme throughout the entire design system. The theme needs to be available when designing, and when coding, and it needs to be easily shared throughout the organization.

What exactly is a theme?

A theme is a variable system that determines stylistic features of a design’s visual atoms. These theme variables — which Salesforce calls design tokens — are referenced when building your design. Beyond just colors and other constants, a theme can also contain component specific styles. This is possible by creating a multi-tiered variable system — as defined by Brad Frost. He breaks it down into 3 tiers:

  1. Brand definitions
  2. High-level application variables
  3. Component-specific variables

With a multi-tiered system like this you have a lot of power over your design from the theme. But, with great power .. comes a lot of complexities.

Defining a theme is no problem, but what is it actually? How do we make it tangible? Where does it live? How do I make a visual of it to add to this post?? These are complex questions. A theme is built into design and code in different ways. It’s hard to create a single source of truth for a theme.

Currently, my best working solution includes making the design library (made with Figma, XD, etc) the single source of truth. This can be done by enforcing a good workflow + visual regression testing + continuous integration. If you engineer a proper CI process your design library will be the single source of truth for all design — themes included. To make a change to your design you must first make the change in Figma/XD/etc. Next, you make the change in your code component library. With the help of our CI process and visual regression testing we can ensure no code is allowed to be pushed until the design change is reflected in the code. In a future post I’ll explain this process in detail.

Building a themeable design system

Let’s work through everything you’ll need to know to build themeability into your design system. First we’ll focus on the design and we’ll build a themeable component in Figma and XD. Next, we’ll look at different solutions to implement the theme in code.

The plan

For a clear example let’s create a single component with a few themes we can apply to it. We’ll design a simple card and use these themes:

  1. Default theme — A defaultish looking theme.
  2. Dark theme — Like default but inverted.
  3. Wireframe theme — A theme used to design wireframes that can easily be toggled for high fidelity designs.

Theming with Figma

First, I want to mention a plugin that might work well for you: Themer. Themer allows you to easily switch themes by changing Styles published to your team library. This is a great solution if:

  1. You only need simple Style changes like colors and typography.
  2. You’re okay with an all or nothing theme approach — you can’t have one component using theme A, and another component using theme B.
  3. You have no style overrides at the component level.

For me, this is too limiting and doesn’t align well enough with our previously defined multi-tiered variable system; as I’ll likely need to change more than the Figma Styles that are available to change. For those reasons — I decided to create the theme at the component level via themeable components.

When using a component, Figma gives you the ability to make some overriding changes to the content. You can toggle the visibility of layers, and change the Styles in the component — even within other components nested within this component. This system is Figma’s (and XD’s) alternative to Sketch’s Symbol system. Their component system is simpler and easier to use, but results in less flexibility. In my opinion — you likely don’t need that flexibility, and the trade off for better usability and better UX is worth it. Especially worth it as you start to scale your design system across an organization.

Create a themeable component with Figma

TLDR: Add Design Tokens as Styles. Then, create a “Master” component that will contain a separate component for each theme as layers. Use the Master component in your working designs and switch themes by toggling the layer visibilities.

Create your Styles: Save your Design Tokens into Figma via Styles. Figma allows styles to be defined for Color, Text, Effect, and Layout Grids. You can group your styles for each theme by using a naming convention. Example: `Default/Primary` or `Dark/Primary`.

Saving Design Tokens as Figma Styles

Create the Default “Theme Component”: Create a new component and name it `Recipe Card — Default`. Build out the default theme design for your card in this component.

Creating a Figma Wireframe component

Create the Wireframe “Theme Component”: Create a new component and name it `Recipe Card — Wireframe`. Build out the wireframe theme design for your card in this component.

Creating a Figma Theme component

Create the “Master Component”: Using your Default and Wireframe components create a `Recipe Card — Master`.

Creating a Figma Master component

Use your new component: Use the Master component when working. You can now easily choose a theme for this component by toggling the layer visibility. You can also make override changes to the local component.

Using our new Figma Master component

Theming with XD

XD has a powerful feature that makes it the ideal tool for themeable components: Component States. Instead of Master Component + Theme Components we can use a single component, and add a new state for each theme. As you scale your design library this will make a huge difference in how you organize your components.

Similarly to Figma, you can utilize Styles for some of your Design Tokens and it is an analogous experience. However, there are small differences: XD doesn’t group your Styles via naming convention, and it doesn’t let you use the same color multiple times. This can be problematic if more than one theme uses the same color.

Create a themeable component with XD

TLDR: Use Component States.

Create your Styles: Save your Design Tokens into XD via Styles.

Saving our Design Tokens as XD Styles

Create your component: Create a new component and name it ‘Recipe Card’. Build out the default theme design for your card in this component.

Creating an XD Themeable Component

Create your Wireframe “Theme State”: Instead of creating a new component for each theme, we can use component state. Create a new state and name it ‘Wireframe’. You can make any changes you want in this state. Build out your Wireframe Recipe Card theme.

Creating the component’s Wireframe theme via XD State

Use your new component: You can now easily choose a theme for this component by changing the state. You can also make override changes to the local component.

Using our Figma Themeable Component.

Coding your theme

How you code your theme depends on your underlying architecture. If you’re using CSS then CSS Variables are a good place to start looking. If you’re using CSS-in-JS then JSON is a great solution. I’m a big fan of CSS-in-JS, and I think it’s a better fit if you need theming — especially run-time dynamic theming with component specific styling. Here’s a very simple example of our Default theme as JSON.

This is a simple example of a theme specification. Once defining your specification it’ll be hard to make changes. The specification will need to define all your current and future themes. Your code will be tightly coupled with this structure once you start using it. Take your time and create a holistic specification that can scale. This Theme UI github issue is an awesome resource to help you get into the mindset of creating an extremely robust specification.

Theme UI is a great resource for building themeability into your component library. Definitely check them out, and — at the very least — dig into their theming implementation before you start working on yours.

Where do we go from here

This is all great, but it leaves me wondering how we can improve. Our single source of truth is merely a facade. In reality the theme is split into Figma/XD Styles & Components, along with CSS Variables or JSON.

We can add some CI magic to help keep everything synchronized, but I wonder if there’s a better way. My dream is for a design tool that can work with JSON (and npm). Imagine editing a theme via JSON and instantly seeing those changes reflected in our design tool and code. Imagine, creating a new theme by writing structured JSON, based on a detailed specification, and having it instantly available to use in design and code. ImAGine creating a theme builder with a beautiful UI — used to design themes that can be exported directly into our theme repository resulting in a new theme that anyone in your organization can instantly start using everywhere!

Maybe one day.

Nevertheless the point stands — themeable design systems are complicated to build. Take your time to architect a system that is holistic, scalable, and robust.

--

--

Builder of software with a passion for learning. I specialize in web development and user experience design. www.kolbysisk.com