Theming a design system
Outlining our thought process for tackling the thorny issue of theming colour in the Kingfisher design system.
Theming is a way of customising a user interface to better reflect visual identity. A theme defines the stylistic features of the UI kit, such as typography, colour, border radii, sizing and spacing. What it doesn’t do is touch on functionality, allowing for a clear separation between how something looks and how it behaves. Put simply, theming lets us code a component once but style it in multiple ways.
This was of particular importance to us when creating Realm (the design system here at Kingfisher), because we support products for a group of companies — each brand has a unique look, feel and personality that we need to respect and carry into the digital space.
There’s many ways to theme a cat
From day one we knew that being able to theme designs was a non-negotiable requirement. But before we dove too deep into planning an implementation, the team wanted to understand the options for actually performing any kind of brand swap, as that would have a bearing on our decisions.
Of course, we could do it manually. By linking each theme to a design file, a Designer can change which one an element or component is extracting values from by hand. It would be a time-consuming and inefficient process, but it would work. Understandably, no-one was particularly keen.
Alternatives then. Figma itself has in-built Swap Library functionality that lets a Designer to change which theme a design file is pointing to. This is a much faster and more streamlined process with only one potential drawback — it changes everything in the file. We often need to demonstrate designs for different brands on the same page, so we had to take that requirement into account as well.
Lastly we considered using a Figma plugin. Themer for example allows Designers to generate themes and swap between them in two clicks. Plus, they can choose to swap anything from a single element to the contents of an entire file. On the flip side, it requires more in the way of initial setup, as well as a continued reliance on a third party JSon service.
Ideally we wanted write our own plugin that we had control over and that had all of the functionality we needed. For launch, we decided to use Themer as our initial way of working and iterate on it at a later date. Satisfied with our direction, the team could now investigate putting our theming ideas into practice.
Working with a single brand
We began by thinking how we might approach the problem if we only had one visual identity to worry about — what would be the simplest way to make things work? We used B&Q as our starting brand, and the Primary Button as an example component that needed to reflect their look and feel.
B&Q’s brand guidelines clearly defined their main colour palette, typography and graphic design style, as well as rules and governance for how these should be used across different media formats. Aligning to this, we could create Figma colour and text styles in our theme file ready to be laid on top of our library components.
Then when it came to our Primary Button, we needed a colour for the background and another for the text label. With just this brand to factor in, we would simply be able to make selections from the main palette, and apply them to the elements. So as directed by the guidelines, we picked the primary brand colour of ‘Orange’ for the fill and ‘White’ for the label so that Button aligns with what B&Q expect to see.
If we continued along this route, we would then use the same method for all the other components we create, until we had a complete library with branding supplied by the B&Q theme file. Great.
But we didn’t just have one brand, we had five.
Adding a second brand
We needed to see how our initial model would hold up if we threw Castorama’s brand into the mix.
Again, we had a guidelines document for Castorama to use as our reference point and immediately we could see that we would need to make some adjustments.
It was clear that whilst the main colour palette had some alignment to that of B&Q, there were plenty of differences we had to consider. Each brand had a primary colour; ‘Orange’ for B&Q and ‘Blue’ for Castorama. They both had a standard ‘White’ and ‘Black’. But in addition, Castorama also had a secondary brand colour of ‘Yellow’, as well as some grey tints to round out their palette.
In order to be able to swap the look of components between brands quickly and easily, regardless of whether we used a plugin or Figma itself, each style used in the B&Q theme needed an equivalent in Castorama’s. The styles also had to have exactly the same name for this to be successful.
‘White’ and ‘Black’ both mapped like-for-like across the brands, but ‘Orange’ was obviously not ‘Blue’, and there was no equivalent at all in the B&Q palette for the additional secondary ‘Yellow’. That meant the naming convention we’d started with wasn’t going to work, and would break if we tried to swap the colours used in our Button.
There were two approaches we could take here. The first would be to duplicate the B&Q library, change the palette out for Castorama’s and apply the new colours to every element. Sure, that would mean that each component would come in with the correct brand colours, but now there would be two libraries to maintain whenever we wanted to make an addition or a change. The solution just wasn’t suitable for working at scale.
A much simpler idea was instead to adapt the naming convention of our colour styles to make them less specific and more generic. That would give us a like-for-like identifier across both brands, even though the hex code that sat behind them was different. So instead of the very precise ‘Orange’ and ‘Blue’, we would use an all-encompassing ‘Primary’ instead.
Now when we took the Button and applied the new theme to it, it was successful. ‘Primary’ in B&Q mapped across for ‘Primary’ in Castorama, whilst ‘White’ was a straight swap. The component looked the way it should in both brands.
There was still that niggling secondary ‘Yellow’ floating around though that didn’t have an equivalent mapping and that would no doubt be needed on some Castorama versions of components. So we knew this method had limitations and decided to circle back to that extra colour later on.
Adding a third brand
And how robust would this iteration be? It was time to bring a third brand, TradePoint, into our model to find out.
Another brand, another set of guidelines and colours, again very distinct from the previous two. That was OK though, because we could follow the generic naming convention again with little issue.
We then applied the styling model to the TradePoint themed Button and…
Chaos.
‘Primary’ as the background colour and ‘White’ as the text colour would give us something not only off-brand for TradePoint, but also with completely inaccessible colour contrast. The rule we established no longer worked — the text for TradePoint needed to be ‘Black’ and we couldn’t swap out ‘White’ for ‘Black’ as the names didn’t match.
Realms’ theming solution
We’d already ruled out duplicating libraries, so we needed to go a step further.
Rather than applying colours directly from a single palette, we created two new styles to hold the values that Button needs — ‘Background’ and ‘Label’. Then we could choose which colour from the brand palette to assign to each style. These would also form the basis for our tokens; named entities storing the visual design attributes.
Now B&Q, Castorama and TradePoint all had the colour values their Button needed, but crucially the names given to those values were the same for all three brands. When we took the component and applied our new styles, we were (at last) totally successful. ‘Background’ and ‘Label’ provided the right colours to the right elements, and Button looked the way it should in all three brands.
“But what about that extra yellow colour?” I hear you ask. Not a problem. With this method, it didn’t matter that brands had completely different sets of colours. The palette provides all the different choices available to a Designer — they can then make a decision as to which one is best suited to a particular component element and select that colour for the element style, giving them creative freedom.
The only compromise would be that number of styles contained in the themes will increase depending on how many components they have to cope with and their level of complexity. And since a theme file wouldn’t be something that updates or changes on a daily basis, this didn’t feel like too much of a compromise at all.
Jerry’s final thoughts
Theming is a fundamental building block of our design system, and making it work was one of the bigger challenges the team faced. The solution we arrived at suits us well, but we always recommend devising something that fits your business and requirements, as it likely differs from ours.
For us, we don’t have to compromise on individual stakeholder identity, and Designers are able to see designs in different themes with a couple of clicks. Theme files can just as easily be used to generate a light or dark mode, meaning we can scale and grow into new scenarios without refactoring.
I’ve mostly talked about colour here, but our themes can quickly control typography and effects for each brand using the same method. A set of consistently named text styles exists in each theme, but the font faces, sizes, line heights etc that live behind those aliases can change per brand.
Having companies with unique brand presences’ is a strength, and our goal is to support this in our digital products. Over time we aim to grow the system so that in addition to everything currently on offer, we can provide even finer control over look, feel and sizing. That control can ultimately pass to the brands themselves, because who knows their house style better than they do?
The team are looking forward to seeing what Figma have in store for us in 2023, because design systems (and theming) are only going to play more of a role in Product Design as time goes on. As for what we have in store, there’s plenty more from us at Kingfisher Design here on Medium.