Hello.

Welcome to the Battlefy Arcade writeup. This is a bit of a long one but those who love the detail and want to see how we actually built Arcade, get stuck in.

After the initial requirement gathering and after writing up a list of generally “expected” components (buttons, text inputs, as well as foundational elements which included colour, typography etc), we started looking at how it would function within our own contexts. Looking at Portals, we had a typical layout that we traditionally stuck to, so our goal for our MVP was to create a portal using the components we made and be able to apply styling to those.

This layout was as followed:

  • Global nav

  • Hero

  • Subnav

  • Onboarding

  • Prizing

  • Tournament cards

  • FAQ

  • Footer

A relatively simple question? Sure! [Insert massive asterisk here]

A few things that kept coming up was the difficulty behind making these components flex to the right amount so that they can be used across portals where you need to apply brand styling, and also change tokens of a particular element. 

Lets, for example, take a button. Simple enough, right? Nope! Think of all the different variations you could have in terms of type, interaction, relationships, iconography etc. Each of these needed different levels of foundational tokens as well as more complex elements such as iconography, border radii, spacing etc. These also needed to be easily handed over to developers, be easily scalable, easy to add to and also be able to be tweaked simply at a later date.

Simple.

Oh, and all of these needed to be able to be changed without committing the Figma-based cardinal sin - ⌘ + ⌥ + B - detaching a component. The ultimate failure in creating an actually useful design system.

Whilst I was researching what possibilities we could use to create, a Figma plugin called Token Studio kept appearing. This was designed to be able to easily tokenize elements of a design object and output that as code. After discussing with developers and the design director, we decided to go with this option. Now, what was it that Token Studio did?

To understand Token Studio, we’ve got to understand the layering system we decided to use in order to make sure our tokens were the most effective. At our bottom level, we had our raw values - our base layer. This consisted of scales of colour from 0 - 100 in terms of luminosity, typography scales for size, line height, letter spacing, units of 8 to be used for spacing and padding directions - base, core elements of a system. 

These however are not where the power of our system was rooted though. The real trick was the layering we could apply to these elements. To do that, let’s talk about how we generate a primary colour.

At a base level, our primary colour was a 70% lumosity version of a purple hex code, originally based on a secondary colour we had floating around on the site. Our actual primary was red but we stepped away from this for the MVP of our design system in order to avoid clashing with any error states.

This primary colour is referred to as `base.color.primary.70`. That breaks down to what set it belongs to - base, what it is - colour, what type it is - primary, and what unit of that scale it is - 70. Now `base.color.primary.70` as a reference point kind of sucks. It’s impersonal, it’s not easily understood (what is a primary 70 anyway?) and it doesn’t make sense unless you’re the puppet master behind the design system. Utterly utterly useless. Design systems need to be open, easy to understand and picked up by anyone or their mum and understood. This is where our second layer comes in.

Semantically, our `base.color.primary.70` is our primary, default colour. We need a way to refer to that, so we move a layer up. Creating a new set called `semantic`, instead of creating specific values within that set, we use this layer to refer to the base layer 🤯

Doing this means that when we create `semantic.color.primary.default`, instead of putting a hex code in as the value, it will refer to whatever the `base` set dictates. In our case, `base.color.primary.70`. This sounds small when I write it out as a little sentence on my website but this absolutely changed the way we look at design system flexibility at Battlefy. 

Seeing as we now have two sets that refer to each other, if we have a brand come on board and they say “Hey, I’ve got this colour as my primary and this is my secondary, all my objects have 16px rounding and I love comic sans so make that my typeface”, we can just slot in a brand set in between our base and semantic sets and our semantic set will automatically pick up those new values from brand and we don’t need to worry about updating each and every colour individually across the library itself, creating a literal one-click mass change to design system flexibility. I promise you, that’s a satisfying click.

So now we’ve got two (three with a brand) sets that work together to create a group of tokens that cover most of our design elements. How do we start applying this to actual components?

Well let's look at our button again. What can we call out as specific parts of this design object? We have the colour of it, the typography on it, the size of it, the border radius, padding, gaps etc. On top of that, we also have a filled, an outline and a text-only version of this, each with slightly different styling. 

Where we had `semantic.` and `body.`, we make a new category- `button.`. This means that all tokens with this prefix are exclusively for the button component and make it super simple to identify which CSS properties are being used where. Now let’s start applying that. 

Our buttons at Battlefy had 24px padding on the left and right, and 16px top and bottom, so when it came to creating tokens for it, I would go to the button set and create `button.spacing.padding.top-bottom` which references back to `semantic.spacing.m` which in turns references `base.spacing.200` which in turn references `base.spacing.unit`*2. Complicated but this trail allows for so much flexibility if perhaps a brand wanted to use a base unit of another value perhaps. The same works for `button.spacing.padding.left-right`. Tokens are named purposefully, with a semantic focus, making them easy to understand and spot if we’re missing anything. 

At the same time we create these tokens, we directly apply them to the component within the Figma UI library, meaning that if ever that changes in Token Studio, those changes will be then immediately reflected in the component itself.