Writing

← Writing

Automating the boring parts of product design

March 15, 2020

We started building the GitHub mobile apps last May, around the same time that Figma Plugins were released. I remember feeling so relieved, because I suddenly had access to tools that would speed up my design process, simplify tedious workflows, and automate the boring parts of designing screens.

Over the next few months, I ended up making about ten small utility plugins. Those small utilities were eventually combined into a single "mono-plugin" that has become my daily-driver for designing the mobile apps.

Bottom separators

iOS table views use separators between list items to improve the scannability of lists. Separators are inset from the left edge of the screen to align with any text within the table cell. As I was designing many new types of table views, it was tedious to constantly resize these separators as content dimensions changed.

The first plugin was a text input that accepted a string like t, 16 and would apply a top separator and a bottom separator inset 16 points to any table view cells that were selected. As you can see, I really poured a lot of love and care into making this plugin aesthetically pleasing and delightful. Dribbble isn't ready for this much joy.

Creating color styles

We knew we wanted to ship our mobile apps with dark mode support out of the gate. This meant that we needed to extend the Primer color system to account for dark mode variants. The next utility plugin took the original set of Primer styles and extended them into a mobile-only "spectrum color set" that contained dark mode variants.

For each mobile-specific color swatch, the plugin would generate color styles in the Figma document.

Functional color styles

In general, I don't recommend using colors like gray-600 as values in interface designs. Interface colors should live within a second layer of abstraction that we call "functional colors."

For example, we might create a functional color called textTertiary that encapsulates gray-600. A functional color can encapsulate multiple color styles to account for theme variants. In this way, you could have textTertiary / light mode and textTertiary / dark mode.

With a few dozen functional colors, extended from the base set of a few hundred core colors, I was suddenly dealing with a lot of color styles in my document. So the next plugin ran colors through a pipeline that ensured that my mobile colors extended Primer, and that my functional colors were always derived from the spectrum palette.

The resulting color pipeline looked like this:

Color export

We needed a way to get all of our color styles out of Figma and converted into xcassets and XML styles for iOS and Android. Copy-pasting hundreds of values seemed tedious, to say the least.

The next plugin grabbed all the color swatches from a Colors page and generated an array of color objects, each with useful metadata like mode (light or dark, high contrast or normal contrast), hex values, and even extended hex values with alpha (for Android).

Eli Perkins and Elise Alix then wrote custom scripts that could ingest this array and spit out platform-specific color asset files.

Color picker

The built-in Figma style picker is not great. It doesn't support search, it constantly resets scroll position, and long style names get truncated. After programmatically creating a few hundred layer styles, I knew that I'd need a better interface.

The next plugin wrapped the document's layer styles in a modal with search, preview swatches, and utility buttons to set layer properties for a given color. For example, the S and B buttons on each color's list item would set a selection's stroke and background colors, respectively. Clicking anywhere else on the list item would fill by default.

The color picker also accounts for what mode I'm designing in: the dark mode switcher at the top loads only dark mode variants of the document's color styles. This quick preview made it much easier to debug incorrect dark mode colors.

Dark mode switcher

Designers don't need to design every single screen for both light and dark mode. It's designing at the wrong layer of abstraction: dark and light mode are functions of an underlying color system.

Yet, when making mocks, I found myself wanting to gut check that I had correct elevations, type hierarchy, and contrast ratios in dark mode. Because my color styles were all named with a structured hierarchy, like textPrimary / light / normal contrast I could programmatically swap layer styles by looking for pairs. So given a selection that had a fill color of textPrimary / light / normal contrast I could check that textPrimary / dark / normal contrast exists in my document. If it exists, swap the style IDs.

Data population

Populating mocks with avatars, names, usernames, and bios is tedious. I found myself constantly switching between my browser and Figma to grab accurate data. Luckily, Figma can talk to the internet, which meant I could write a small utility that would hit the GitHub API and return data about people, organizations, and repos.

By naming layers with a special syntax like __login I could tell specific layers to consume fields from the API response. I added a text input that would accept custom variables in case I needed to get data for a specific object; otherwise, the plugin fetches randomly from a hard-coded list of objects.

This plugin has been open sourced as  figma-github-data.

Mono-plugin

After building all these utility plugins, it became tedious to remember all the command names and constantly switch between multiple plugins while designing a single screen.

The solution for this was to combine most of the plugins into a single "mono-plugin" that wraps different commands as buttons. So rather than typing the command "Convert to dark mode" there is now a button that I can click to perform the action. This window is my own personal augmentation of Figma's interface. I can open it once for my entire working session.

Conclusion

These plugins have saved me hours and hours of boring, repetitive work. They're also fun to build!

My recommendation for other designers is to keep an eye out for behaviors that could be automated with plugins. Here are a few behaviors that should throw a red flag:

  • Constantly switching between the mouse and keyboard to perform a task
  • Searching through the layers list for specific layers
  • Selecting many similar kinds of layers at once, across many frames
  • Hiding or showing layers to reflect state or variants
  • Scrolling through property lists, having to set many of the same properties
  • Finding and applying layer styles
  • Using data from the internet to populate mocks

Designers should feel comfortable building their own "personal API" in order to solve their day-to-day design problems. If those problems can be generalized and abstracted, it makes sense to publish and share that work more broadly with the community.

But it's okay to not publish everything. It's okay to just build for yourself. Everything we build doesn't have to be packaged up, marketed, and have a shiny coat of paint.

Demo

I presented this post as a lighting talk at Figma's Config conference in February. My co-presenters Jake Miller and Lily Nguyen also demoed their impressive plugins that are being used at Atlassian and Uber.

Resources

You can grab the figma-github-data plugin on GitHub to see how it works, or fork it for your own team. The Figma Plugins API docs are solid, and should be your go-to resource as you're building your plugins.

I also recommend investigating the following repositories for resources, frameworks, or sample code:

A small favor

Was anything I wrote confusing, outdated, or incorrect? Please let me know! Just write a few words below and I’ll be sure to amend this post with your suggestions.

The email newsletter

Get updates about new posts, new projects, or other meaningful updates to this site delivered to your inbox. Alternatively, you can follow me on Twitter.