How I programmatically built 256 new design system components in Figma

A look into how automation can supercharge the design process

Dylan Babbs
Feb 9 · 8 min read
Image for post
Image for post

Uber’s Base design system offers a set of map marker components that are used extensively across our products, displayed any time we feature a map to the user. We’ve recently come across the need to showcase additional context on the map markers and settled on adding badges — an existing Base component — to achieve that.

The challenge was that both the map markers and the badges had multiple variations. Markers can be customized by size, needle length, icon slots and layout behavior, while the badges can have multiple sizes, label, and icon styles. The final set of badge-supporting map markers is a combination of all these options, a total of 256 new components.

The common approach is for a designer to manually create these new components, which is not only inefficient but very error prone due to the repetitiveness and volume of work required to create all variants and individually test them under multiple scenarios.

I decided to take a programmatic approach.

Image for post
Image for post
Various Base map marker components.

Why did we add badges to the markers?

Badge UI is generally used to showcase an update or an offer of some kind. In this case, the badge is supplementing the marker.

Image for post
Image for post
Size, content, and color can all be customized on a map marker badge.

The design specification for these badges offers four different sizes:

Image for post
Image for post

Since Uber operates in markets where the default language is written from right to left, the badges also support bidirectionality.

Image for post
Image for post
Examples of internationalized map marker badges with both L-R and R-L text direction.

What is the most efficient process to construct the new components?

Once we completed the design specification for the badges, the next step was to “productionize” the components within our Figma workflow. This process entails creating the Figma component for each customization, writing documentation, and then publishing the components to the organization library.

Adding the badges to the map markers would nearly quintuple (5x) the number of map marker components within Base, as we were essentially adding four new badge variations for each existing marker.

For example, the new map marker component naming convention would go from:

  • Map marker / Medium / Icon leading + trailing / Fixed / Needle off

to:

  • Map marker / Medium / Icon leading + trailing / Fixed / Needle off / Badge none
  • Map marker / Medium / Icon leading + trailing / Fixed / Needle off / Badge x small
  • Map marker / Medium / Icon leading + trailing / Fixed / Needle off / Badge small icon
  • Map marker / Medium / Icon leading + trailing / Fixed / Needle off / Badge medium icon
  • Map marker / Medium / Icon leading + trailing / Fixed / Needle off / Badge medium text

Base already contains 68 map markers, so repeating this process 68 times would be quite the tedious task.

To complicate matters even more:

  • each badge was to be positioned in a different relative position on the marker’s top right corner, depending on both the size of the badge and marker.
  • only certain badges were eligible to be placed on each marker. This eligibility depended on the size of both the badge and marker.
Image for post
Image for post
Table referencing pairing eligibility and relative pixel offset positioning information for map markers and badges.

Accounting for these constraints, a total of 256 new badge-supporting map markers would be created. Seeing the large number of permutations that I would have to build, I knew this would be a daunting manual process with lots of repetitive mouse movements.

Constructing these new components by hand would be a significant time investment that would most certainly lead to human error due to the pixel precision required of repetitively positioning each badge on a marker hundreds of times.

This type of monotonous task was a perfect candidate for replacing with automation with the Figma Plugin API.

Automation via the Figma Plugin API

The Figma Plugin API enables one to programmatically interact with the Figma document with nearly a 1:1 feature parity compared to normally interacting with the traditional UI. One can traverse the document as a node tree, create and modify objects, configure the viewport settings, access shared styles, and much more with the plugin. For those familiar with the web’s DOM (Document Object Model) API, the Figma Plugin API is very similar.

Image for post
Image for post
Creating a frame and modifying its properties with the Figma Plugin API.

Uber has an extensive internal Figma ecosystem of plugins and tooling to augment the design process. Getting started with creating a new Figma plugin at Uber is relatively low-effort, as scaffolding is available to help with the initial plugin creation, testing, building, and publishing processes.

You can learn more about Uber’s Figma plugin ecosystem on the Figma blog.

Configuring the Figma API to construct the new components

I began to write the step-by-step process of the map marker construction algorithm to be implemented in Figma.

Since each badge and marker contained specific sizing and positioning logic, I created a configuration object in code to hold this logic. This object contained badge positioning and pairing eligibility information.

The Figma API plugin code would conduct the follow tasks:

  1. Query all eligible map marker components to append badges to. Only certain map marker badges were qualified to contain badges.
  2. Loop through queried markers and look up eligible badge pairings.
  3. If the marker had an eligible badge pairing:
  4. Look up placement position info for marker + badge combination.
  5. Using some auto layout trickery, append the badge to the marker in the correct relative position. This step was the most time-intensive, as I had to replicate and encode many Figma auto layout rules into the object programmatically. At this point the new map marker badge component were created.
  6. Neatly place the newly constructed map marker badge component in the main Base component document.
  7. Repeat for all remaining markers until the process is complete.

Executing the script was simple at this point. In the plugin’s UI window, a button click kicked off the script execution. All I had to do was click Build Markers, and the plugin would work its magic.

Image for post
Image for post

With just a single click, I was able to take a set of markers and badges and automatically bind them together to create hundreds of new Figma objects programmatically.

Creating the script was definitely an iterative process to nail every step of the component construction. However, the beauty of scripting in this situation is that I could dynamically undo and repeat the process repetitively until the output was exactly as I desired. There was no need to manually step back or reset the document by spamming the undo button. The entire workflow could be executed or completely reversed at once.

Testing markers at scale

At this point, the new map marker badge components were constructed, but the process was not quite complete. I needed a methodology to test these markers at scale to root out any potential positioning or sizing issues that may have appeared as a side effect of the script. Having a scalable testing framework available would also be important in the event the root components were ever changed in the future.

I wanted to test for two criteria:

UI test 1: badge positioning

The badge’s relative offset positioning depended on both marker and badge size. For example, some badges would be -3px offset, while some badges would be -5px offset.

Image for post
Image for post
Positioning examples for two different types of markers

In order to test this, I decided to automatically generate guides placed in the desired position of each badge using the plugin API. With these guides in place, I could perform an eyeball test to ensure each badge was positioned properly. Both a horizontal and vertical guide would be placed on every single new marker.

Image for post
Image for post
The automatically generated eyeball guides, with positioning specific to each marker-badge combo, could be toggled at anytime.

UI test 2: text length

The next test I implemented was to ensure proper badge positioning based off marker and badge text lengths. The length of both the marker and badge could differ on each custom instance of the component, depending on its usage.

To implement this test, I created two input fields within my plugin UI so that I could specify custom strings. This way, any text that I would enter into the inputs would propagate down into all the map marker components. This would let me ensure the badges stayed fixed in the correct position, no matter the length of the marker or badge text.

Image for post
Image for post
Updating the text content of all markers at once.

Wrapping up

As design systems grow and mature, the complexity of the components increases with it. This additional complexity opens up room for human error due to the repetitiveness and volume of work required to generate all variants — even without errors, such a manual process is highly inefficient. And with a design system that is being used at scale, even small errors can get compounded and deteriorate the user experience. By incorporating automation into the design system workflow, we can create a high quality set of well-tested, production-ready components.

By automating the construction of the markers, I was able to avoid human-error and efficiently generate the full set of variants. Programmatically testing the components allowed me to thoroughly validate them under multiple scenarios and be confident of their quality.

Give the finished components a try in the public Figma Base Gallery.

Thanks to my colleagues Cady Wachsman, Vietanh Nguyen, Anton Chang, Christian Rauh, and Joshua Lee for the help throughout this process.

Uber Design

We are passionate about the pursuit of ideas that put…

Dylan Babbs

Written by

Maps + Design+ Code. Product Designer at Uber. Twitter: @dbabbs

Uber Design

We are passionate about the pursuit of ideas that put people first. Work with us: uber.com/design. Follow us on Twitter: @DesigningUber.

Dylan Babbs

Written by

Maps + Design+ Code. Product Designer at Uber. Twitter: @dbabbs

Uber Design

We are passionate about the pursuit of ideas that put people first. Work with us: uber.com/design. Follow us on Twitter: @DesigningUber.

Medium is an open platform where 170 million readers come to find insightful and dynamic thinking. Here, expert and undiscovered voices alike dive into the heart of any topic and bring new ideas to the surface. Learn more

Follow the writers, publications, and topics that matter to you, and you’ll see them on your homepage and in your inbox. Explore

If you have a story to tell, knowledge to share, or a perspective to offer — welcome home. It’s easy and free to post your thinking on any topic. Write on Medium

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store