Designing & developing useful utility plugins for designers

Date: 2019
Role: Product Designer, Developer
Shortly after I switched to it, Figma announced the possibility of extending the application functionality with plug-ins. I decided that it was a great opportunity to get to know the tool better, and at the same time solve some of the problems that I faced in my daily work.
I mainly focused on alleviating the routine activities that designers have to deal with many times a day. My goal was to simplify such interactions and free up time for really important tasks.
On the subject of accessibility and usability, I gave a presentation at the Figma Plugins Show and Tell.
Therefore, an important thing for me was to make the plugins keyboard accessible and the interaction itself as smooth and seamless as possible.
Here I will show the process of designing and programming them and some of the challenges I faced along the way.
Table of content
Use these quick links to jump to stories about plugins
This plugin is one of the simplest. In Figma, you can use shortcut Shift+Enter to go one level up in the list of layers. Unfortunately, this is quite an uncomfortable shortcut, because you have to move your hand every time from the left part of the keyboard and back, and the combination itself is not too easy to press with your left hand.
For such a frequent operation is very wasteful, and you can not assign your shortcuts to native functions in Figma yet, but you can assign them to call the plugin. So I made a simple plugin that duplicates this function of the Figma. Now you can assign your keyboard shortcut to call the plugin. By analogy with Sketch, I have assigned mine to Cmd+Esc. Now you don't have to move your hand and glance at the keyboard every time you need to select the parent layer - a good time saving for such a frequent operation.
This plugin is similar to the previous one. It also just allows you to bind the native reset instance size functionality to the shortcut. It is convenient when you replace one instance with another and want to quickly reset it to its original size.
It's a port of one of my Sketch Plug-ins, and since figma now replaces instances in original size from the beginning, it is not so useful now, but still can occasionally save you a click.
This plugin is a little more complex and allows you to simultaneously change the text in multiple layers.
Often you have several copies of frames in which you have, for example, noticed a typo or decided to tweak the copy. Changing texts one by one takes time, but solutions like "find and replace" plugin also requires several steps. You just want to select all the necessary layers and change the text there at the same time. And this is the ideal case for this plugin.
Here are a few details:
• If all selected layers already contain the same text, it will be shown in the placeholder. This is handy when you don't need to replace the text completely, but only need to correct it a bit, for example, to correct a typo or add something at the end.
• Of course, I have made sure that there are no unnecessary steps when using the plugin. You can just call up the plugin (I've also bound it to a shortcut) and start typing, the field is already focused and preselected.
• The plugin changes all the visible layers found inside the selection. It should be used with caution, but it can be quite convenient. For example, if you want to change the text in buttons, it is not necessary to select the text layers inside, just select the buttons themselves.
One more interesting detail: work with fonts. If a font is not available (e.g. not available on a particular computer), Figma will not change the text. Therefore, I needed to somehow solve the situation where part or all of the text layers have a missing font.
There were several options:
1. Replace the font with a default, and then replace the text. This is the worst option, leaving the user unaware. Don't do that.
2. Replace the text only at available layers and report an error. That's not good either. The plugin says, "I changed something there, but something went wrong. Good luck finding the problem, I'm heading off." Not too user-friendly.
3. Report an error and refuse to change it at all. Here we report the problem before the plugin works. It's a bit better, but still leaves a user with the question "and now what?"
4. Report a problem and ask what to do. Much better. The user is informed about the problem and can decide for themselves whether they want to change the text only in some layers, or prefer not to replace it at all.
However, I decided to go even further. Of course, the issue with missing fonts is a non-standard situation and should be solved by the user, not the plugin. But what if we try to imagine what the user will say when seeing our warning? "Oh no, I must find these layers and go fix the problem". But by this point, the plugin already knows exactly which text layers it cannot change. That's how we come to the final version:
5. Report the problem and ask what to do, while offering some help. Now, in parallel with the proposal to replace the text on the normal layers, the plugin will report on the number of missing layers, and offer to select them so that the user does not have to conduct its own investigation. Here how it works:
After working on the missing fonts case in Bunch Тext Changer I decided to also release a separate mini-plugin that highlights all layers with the lost fonts on the page. The Figma doesn't allow you to do so natively, so I almost accidentally got another useful utility plugin.
Before Figma I was working with Sketch and there components are automatically created on a dedicated page.
Although it is quite convenient to create and play with components right in the place, but for sake of predictability it is still useful to keep them in one place. To move an already created component to a separate page, you need to perform quite a lot of actions: duplicate the component in place, re-select the component, cut it out, go to another page and paste it there. And so for each of them, only one at a time, like that:
It's exhausting, so I decided to make a plugin that will allow you to do it semi-automatically, so when you call the plugin in place of each component inside the selection, it creates its instance, and the components themselves move to a separate page. Here are a few details:
Component page creation and reusage The page itself is created if it doesn't exist, and is reused if it has already been created. Once created, you can rename it or move it, everything will work as it should.
Around the same time, Tom Lowry created a similar plugin aimed at creating a component right on a separate page, just like in the Sketch. I talked to him, and added a condition that if the document already has a page named Components or Symbols, the plugin starts using it. Tom did the same thing, so you can work with both plugins at the same time, and both of them will place the components on the same page.
Working with selection I wanted to make a fairly flexible tool, so the plugin works inside the selection. Sometimes it's more convenient to transfer and sort components in meaningful batches, but of course, you can still select everything on the page with Cmd+A shortcut and transfer all components at once.
Landing frame concept In Sketch, a new component always appears on the page to the right of the rightmost component on the page, but is aligned to the topmost component on the page. Because of this, it is often unclear where exactly the component got to. I wanted to avoid this problem in my plugin.
So I came up with the concept of a landing frame. All sent components appears in this frame, from where they can be reorganized on a component page. After creating the frame, you can move it to organize space your way. This allows you to have a predictable place for arriving components and not to waste time searching for them.
Two commands for different modes Sometimes you want to send components without interrupting the flow to deal with them later. But sometimes it is useful to jump to the page with newly sent components and move them to the right place straightaway.
To address both scenarios, I made two different commands. The first is "Send to component page", just makes copies and moves components, the second is "Send to component page and go" does the same but also moves the focus to the component page and selects newly sent layers.
This is how it all works together:
This one is all about cloning and renaming. Dragging while holding alt is fine, but sometimes created clones must also be renamed. Copying and renaming frames manually is tedious and requires multiple switchovers from mouse to keyboard and back.
In the case of components, the situation is even worse. By default, a component instance is cloned, and to create a clone of the component itself, the instance has to be unplugged and created again. When you also have to rename the received components, the number of actions is simply inadmissibly large:
I thought that instead of singling out and renaming each copied element one by one, it would be much more convenient to name all the copies at once, in one approach, and then create the copies already named correctly.
I wanted the whole process to be as smooth as possible, and ideally take only one approach to the keyboard, so the first problem was the unknown number of copies beforehand.
a. Number of copies problem
We can put several fields underneath one another, and switch between them via the Tab, that's naive and perfect, but you have to know how many copies the user needs. How do we do that?
You can put a "add a copy" button, but it kind of kills the whole idea - each copy requires a different button click. Even if you position the button so that it doesn't move, you'll have to click the button several times to "create" the interface. This is an extra step, and an extra load for the user. Not cool.
You can add a few fields in advance , deciding that in most cases more than let's say five copies will probably not be needed, and if necessary, well, you will have to use the button to add. It's a bit better, but it's still a lazy and inelegant approach.
So I decided to go further, and implement manual behaviour for the Tab button . Now, when you press Tab, so far the last of the existing fields is highlighted, a new field is created underneath it and the focus is taken. While it's an unusual behaviour, this made the experience as smooth as possible: you don't need to know in advance how many fields to "order" from the interface, just type and add copies with Tab as needed.
b. Assisted renaming
Next thing I noticed: if we copy a layer that is named in a slash-convention like this: Button / Big / Primary / Active , there's a pretty good chance that you actually only need to replace the part after the last slash.
Of course, I've put the name of the layer to be copied in the name field so that users don't have to type the whole "address" from scratch every time, but that doesn't really help much. In fact, in this case, we are returning to the starting point: after each copy is created, you have to manually select the last point and only then type the new value.
That's why as the next step I have written regexp, which automatically selects only the part after the last slash if the layer name uses a slash-convention. (No matter if you use or not spaces after slashes it will work both ways)
Now you can smoothly rename even layers with names that have pretty deep nesting. Of course, if you need to change the name of the layer completely, you can select the full name with cmd-a shortcut and change it from there.
c. Copy directions
At first, created copies simply appeared under the original with hard-coded indentation of 20 pixels. While working, I realized that in some cases, for example when copying frames, it would be nice to be able to copy to the side as well as resize the indent.
However, I didn't want to add an extra step with direction selection to the plugin interface itself. Instead, I decided to make four independent commands in the plugin: Copy Downwards, Leftwards, Rightwards and Upwards . This way you can assign commands to independent shortcuts, and do not waste a click on switching in the plugin interface.
You can switch to changing the distance between copies by pressing the Shift+Tab, so you still don't have to grab a mouse. Last used value saved so you can select the needed amount just once, and reuse it after.
And one more little detail. You may have noticed that when you create a new copy, the name inherits the name from the previous one, not from the originally copied object.
This may seem a bit illogical at first, but in fact it adds even more flexibility: this way we can change the nesting level right as we make the copies.
To conclude: Smart Cloner allows you to make your own workflow to seamlessly clone and rename components, frames or any other objects.
One of the most exhausting actions that designers have to repeat once in a while is changing texts.
If you have several text objects, changing texts is quite tedious: you need to select the object with the mouse, go to edit mode, select the current text, and only then type or paste the new text. Even though the guys from Figma made it a little easier, so you can just click on the next layer without having to click through the whole hierarchy, it still takes a long time:
Every time I had to highlight and paste texts over and over again, I was thinking, can't it be possible to change all the texts at once? I already had a working example of the convenience of working with multiple text fields in a Smart Cloner, so I decided to give it a try and solve this problem with another plugin.
The idea was to collect all text layers inside the selection and show them as a list of text fields that could be selected one by one with Tab. This would allow all texts to be typed in one approach to the keyboard. This is what I had ended up with:
a. Multiple lines pasting
But I didn't stop there. Printing texts is cool, but sometimes you already have them somewhere. Of course, there are methods like Google Sheet Sync plugin, but they take a long time to configure. It doesn't work when you just received a list in Slack, or need to insert something from the documentation. Wouldn't it be easier to be able to just copy-paste it?
So I added the option of inserting multiple lines. If you copy the values separated by the line break and paste them into the plugin while holding down the Shift, each next line will be pasted into the next available text field until one of them is over.
Just imagine how long it would take to replace all these texts manually:
b. Missing fonts case
As in the Bunch Text Changer plugin, I have thought of a solution for the case when some fonts are missing. A similar warning is shown with an offer to select all layers with missing fonts.
Additionally, text fields corresponding with such layers are disabled in the list, so you can see in which layers the problem occurred more clearly.
c. Some details
At first, the plugin used one-line input. This wasn't very convenient for longer texts, so I had to redo the input fields so that they could resize the text field as you type.
Also, after publishing the plugin, I found another curious unexpected advantage. The plugin uses common web elements, where the work with non-Latin languages is better implemented than directly in the Figma editor. Thus the plugin allows more flexibility to edit texts in Chinese layouts, and probably other non-Latin languages, too:
"I think Figma Chinese input experience is not that good, but you can try these two plugins!" says Tovi
觉得 Figma 中文输入体验不好的,可以试下这两款插件!
— Tovi (@twooowei) October 24, 2019
Retextifier by @aswellasyouare https://t.co/1G2Qi3pHBi pic.twitter.com/8J6UiifPDw
You can edit existing text styles in Figma only one by going into each style and changing the title or parameters. This is quite slow and not convenient, I wanted to have a smoother and more native interaction with the styles. So Text Styles Generator was created.
Ideally, I wanted a simple scheme: the text of the layer should correspond to the name of the style, and the text parameters should correspond to the style parameters.
When you are creating a style, this schema works well, but unfortunately, it doesn't consider the case when you need to change an existing style.
If we only need to change the name, we can still find a way out by looking at which style has the text with the new name (which no longer coincides with any of the local style names).
But if we also want to change the parameters of the new style, everything becomes more complicated. Unlike the Sketch, Figma doesn't let us change the text parameters until the layer is unbound from the style, and once it's unbound, we no longer know what style to update (assuming that we may have already changed the contents of the layer to its new name).
I wanted to still be able to rename the styles, so I had to go for a slight increase in complexity and use another characteristic that the layer has - its name.
Thus, the plugin looks at each of the selected layers and compares its name with the names of the existing text styles in the document. If such a style is not found, it is created based on the text parameters. If a name is found, the style is updated based on text parameters, and the name based on its contents (i.e. the style is renamed).
In this way, you can rename and change the parameters in any order. Unfortunately, there is one case, because of which users need to understand how exactly the plugin works.
Say, you decided to copy and paste a layer with a style, then detach it from the style and change its parameters and text in hopes of creating a new style. However, the new layer will inherit the name from the original, so the plugin will relate it to the existing style. To create a new style, you will need to change not only the name in the text content but also its name of the text layer itself to what you want to give the style. This can be done semi-automatically, using the Reset Text Layer Name plugin, but it is still an extra step.
In general, this plugin requires an understanding of how it works to use it, which I find not ideal, but at least it allows you to do the work much faster and more clearly, and save a lot of clicks when working with styles.
As an addition, I thought about a case where there are already several text styles in the document that need to be changed. Before you can use the plugin, you will have to create a bunch of text layers and assign styles manually. This is also time-consuming and not fun at all, so I added the Draw Existing Styles command, which will do it for you by automatically creating one copy of each of the existing styles in the document.
That's how the plugin works:
This plugin is all about tidying up. The spacing of elements with equal intervals is what each designer does quite often. In Figma, there are two native functions: Distribute Vertical Spacing and Distribute Horizontal Spacing, which should do just that.
Unfortunately, it is not so convenient to use them. Let's say we need to put the icons in the same row with a gap of 15 pixels, look what you need to do this:
It's a lot of clicks, but most importantly, each time you need to spend the mental energy to figure out which alignment to apply, then separately manage the distance. And that's just one line. Imagine how many actions would it take if you had to spread them out in two lines?
So I decided to make a plug-in that would allow you to easily spread the elements into rows and columns. When you select several items, you call up the plugin and tell it how many columns you want to arrange the items in. That's it.
Additionally, you can specify distances between rows and columns, and they will be saved the next time you call the plugin. This is how it works:
a. Working with selection
Plugin works when you select more than one layer. However, there is one special case. Often you put all the elements of your grid in a group or in a frame. To run the plugin you would normally have to select all of the elements inside of it either manually, or by hitting "Enter".
It is not much, but plugin can still save you a second. So, if you have selected just one Group or Frame when called the plugin, it will apply arrangement to all layers that it contains.
b. Rearranging powers
Another huge plus of the plugin that it's aware of the initial position of the layers and places it in the same order. This allows you to use the plugin to rearrange elements in the grids or insert new ones, without manually dragging all of them.
To rearrange, just place the element's top-left corner in the right position, and re-run the plugin.
c. Special cases
And one last small detail. Of all the possible arrangement options, two special cases are when you need to arrange the elements in one column or one row.
If it's easy to do it in one column, you should always type "1" in a field with the number of columns.
To make one row, however, you need the same number of columns as you have selected items, and you may not know for sure, how many of them you have selected. To make this easier, I've prepopulated the input with a ready-for-edit count of selected layers. This way to have one row of items, you don't have to count layers or, in fact, do anything at all, just call the plugin and hit enter and you have a nice row of items.
That's it for today, thanks for reading! More plugins will be there as soon as released.
You can follow me on Twitter in the meanwhile to learn about updates.