Inside Figma: Behind the scenes of component properties – Su Yang, Naomi Jung

My Dear Friends of Figma in Hello everyone um I’ve been at figma for a couple of years now um but due to the pandemic this is my first in-person event so I just want to say that I’m super excited to be here with all of you today um my name is Naomi I’m a software engineer on figma’s Design Systems team essentially we’re the team that builds.

Features for Design Systems in inside of figma so this means we’re developing features that allow users to create Design Systems maintain and use these systems hi I’m Sue I am also an engineer on the Design Systems team at figma and today we’re going to give you all a behind the scenes into component properties but.

Before we dive into props let’s first take a step back and talk about how components came to be so if you’re a long time figma user you might remember that we first launched components all the way back in 2016. and this was a really huge launch for us because it really built the foundation of allowing larger design teams to scale.

Their Design Systems a couple years later in 2020 we launched variants and this is also really exciting for us because it really just multiplied the power of components letting people create a component set with multiple related components and so we’ve come a long way since 2016 but of course there’s still a lot we can.

Do to make using figma easier so one of the issues that with variants is that designers still have to draw out every single permutation of what they want a component to look like which is really time consuming and we’re increasingly seeing developers start to use figma but developers still have to go into the complicated design file and manually.

Abstract the variant into code and finally people love the idea of variance so much that they really just ran with the idea of it and started creating component sets with hundreds of thousands of variants an issue that we like to refer to internally as variant explosion and fun fact the largest number of.

Variants in a component set is actually 16 000. which is yes a huge number of variants to maintain so to get around this complexity some Design Systems authors have started using what’s known as base components in their Design Systems and here’s just a simple example of a base component but you can imagine that.

So here we only have one nested layer if we have a more complicated component we might have multiple nested layers and then it becomes really difficult for a consumer to kind of select the instance layer that they need to know to change what the component looks like and so even though Bayes components can help Design Systems authors they actually.

Introduce a lot more complexity for Design Systems consumers and it’s not just for figma users that variant explosion caused a lot of issues for it also caused a lot of issues for engineers as well so you might have noticed that when you have a variant selected in figma we let you easily toggle between the different variations.

Without any latency or additional Network requests and the way we’re able to do this is because for each unique variant instance you have in a file we pull in the component set as well so here’s just a simple example if you have a really innocent looking button and you add it to your file we actually add the entire component set into the.

File as well and under normal circumstances this isn’t too bad but you can imagine that in the 16k variant example pulling just one instance of one of those buttons will pull in the entire 16 000 variants as well which can cause this really dreaded red banner that shows you that you’re out of memory and you can’t do anything else in figma.

So after all of these issues we kind of went back to the drawing table after the variance launch and asked ourselves is there anything else we can do to make building Design Systems in figma a lot easier and so that’s when we started brainstorming what’s now known as props so how did we go about um building component properties.

We actually started the initial thinking for this feature almost two years ago which was shortly after the launch of variance um as Sue alluded to so in December 2020 is when we started early brainstorming for this feature here you can see some pictures from our first brainstorming session where our cross-functional team got together to.

Sort of brainstorm ideas for different solutions for some of these issues like varying explosion in February 2021 our designer Shayna created some initial designs for this feature and brought them to design crit where she was able to get feedback from various designers at figma in April 2021 we also continue to get.

More feedback on the direction of our designs by taking some of them to user testing and here we can see that uh internally we also have a lot of noodles in our prototyping um designs and as you can see here it gets a little bit crazy and we actually have an internal slack Channel where we collect some of these pasta pictures but.

This was really helpful because we were able to validate a lot of our decisions around what kinds of flows we wanted to create for this feature in June we started engineering planning now for engineering planning we wanted to be really deliberate about making smart choices so that we can handle a bunch of different edge cases that come.

Up when we’re dealing with components and instances there are actually a lot of edge cases which we’ll dive into a little bit later in this presentation but we wanted to make sure that the engineering data models were really robust and so therefore we spent a lot of time planning out how we wanted to build this feature in addition we also.

Wanted to make sure that the data model was extensible should we want to build on top of the feature in the future finally in August of last year we started the engine implementation which involved writing a lot of code writing a lot of tests and doing several bug bashes as we started to get more and more feature complete.

And then finally in May of this year we were able to launch the feature at config now you might be wondering why did it take over a year for us just to build this one feature and that’s because we had to balance a lot of different product decisions and product trade-offs with engineering costs and we also.

Wanted to consider the direction in which design and collaboration are trending so as Design Systems mature and designers work more closely with developers we’re actually seeing figma components start to become more complex mirroring the complexity of code components so could this new feature.

That we were building help align design components more simply with code components on the Design Systems team at figma we also like to think of our users as belonging to one of two groups either Design Systems authors or Design Systems consumers many of you in the audience today.

Probably identify as Design Systems authors and we consider Design Systems authors to be our power users who spend a lot of their day creating maintaining and organizing large Design Systems The Design Systems they create need to be simple enough for themselves to maintain but also comprehensive enough for a consumer to be able to adapt to a wide.

Variety of scenarios and also self-documented so anyone can just come in and understand how to use a component on the other hand we have DS consumers and consumers can really be anywhere from complete beginners to power users as well consumers probably need to spend their time searching through large large.

Design Systems and also be able to adopt a component to a real life scenario that they’re working with and so these two different user groups have radically different priorities and use figma in very different ways and so with all of these different priorities we had to work really closely with cross-functional Partners to.

Iterate on the product behavior and balance different product and engineering trade-offs so one example of a product trade-off we had to make was in the first iteration of component props when we first started thinking about it we actually wanted to attach props to layer names so you can click on this prop icon and it would.

Open up a picker with a list of all the names inside your component and then you can click on one of those names and then attach a prop to the name now this model quickly introduced a couple of issues for us for example what happens if two layers have the same name or what happens if I rename one of the layers so now it.

Matches another layer and these are all issues that come up because of declarative design principles where the user describes the desired output given the current state but doesn’t tell us the exact control flow this also makes it hard for engineering because we can’t keep the data model in sync since we can’t infer user intent.

From action and so after a lot of brainstorming we came up with a more imperative product design where users can explicitly tell us how a prop should control a layer in this new design instead of attaching a prop to a layer name we’ll attach a prop to specific fields on layers instead which have stable IDs under the.

Hood and this new design is a lot easier for us because you will create a prop first and then select the layers and then attach the prop to those layers and note that this does introduce an extra step for Design Systems authors but we were okay with front loading this complexity here since DS authors are power users.

And authoring only happens once but consumption can happen a lot more times and this authoring complexity also kind of inspired us to build a bunch of other features that we lumped into the component props launch such as select all matching layers and select all matching layers lets you basically select a layer inside a component set.

And then we’ll match all the other layers with the same name and layer hierarchy and then you can easily apply a prop now that you have everything selected so in addition to some of these product challenges we also had to dive into several engineering edge cases and a lot of these stem from the complexity that.

Comes with components and instances so to sort of explain that complexity I’m going to take a deep dive into how some of figma is implemented so you can imagine that as a user you’ll navigate to a figma file either in the browser or in our desktop app when you do so you’re going to download a.fig file from the cloud a DOT fig file.

Is our custom file format which is able to store your file content in that file and then what we do is once we sort of download this fig file we will parse the data and then render the contents so that your file looks like your design that you’ve been working on so what does this look like for most most layers layers that are not.

Instances let’s go ahead and take an example with just frames so let’s say we create a very basic button with some frames text layers Vector layers Etc what would the dotfig file look like well here is a visual representation of what the dotfig file is going to look like.

Each of the layers in our design Maps exactly to one object in the file and each of these objects contains some information so for example the text button is going to contain the following information it’s type its name the content color font size Etc and all this is stored in that file so how does this differ for instances.

And what makes instances so complicated well if we take an example um similar to the one before where we have an instance of a button as opposed to a button frame we would imagine that the Fig file is going to look something like this because we have the exact same layer hierarchy it’s just different because now we have an instance.

However the reality is that it actually looks more like this where we actually don’t store any of the children object layers in the dotfig file and that’s because we can actually infer all the information about the instance from the component it inherits from and so this is a huge sort of memory optimization that we can do so.

That we don’t have to store so much information in the file and so when we’re looking at the instance layer well we’re actually going to store in terms of the object is just its type and the component that backs it so in this case this component is inheriting from the button component or sorry this instance is inheriting from this button component.

So you might ask you know what happens when we add an override when we add an override we have some some data that’s unique to that particular instance so here we might override the text button layer and now it’ll say favorite and so where we store that information is going to be part of the instance object and so we have some additional metadata that.

Provides the override info to implement component props we added yet another piece of metadata to the instance object where we store the props and what you’ll notice is here we have both overrides and props and sometimes they have to intermingle and work together to make things even more complicated you.

Can imagine a very you know complicated layer structure like this where we have a nested instance and the reality is that we actually just store the top level instance for this entire nested instance hierarchy and so there’s a lot of complications and edge cases that occur when we have to figure out you know how do we render the contents of.

This instance and how do we actually show what the children’s properties are when we’re you know rendering your file and so these are some of the edge cases that we have to consider when building features for components and instances so how does this relate to some of the things that we were dealing with when building props well one of the questions.

That we asked ourselves was what does it mean to assign a value to a property so for those of you who’ve used this feature you’ll notice that when we whenever you create a property you’ll have to assign a value to it and one possible meaning for that value is an initial value so an initial value means that when you create the instance or you.

Create a new property we’re going to explicitly assign the value so you could take an example with this button component where we’ve explicitly assigned content equals button when we create an instance the instance is going to explicitly assign the content property on it so what that means is when the component.

Is changed the instance retains its value so for example we could maybe change the main component to say click now and so now its property is actually changed but because we’ve already stored information on the instance we’re not going to change the instance at all so the instance will retain that value another option for what a value could.

Mean is a default value so a default value is a fallback that gets inherited when no value is provided so if we take the same example from before with the button component and a button instance we can see here that we actually allow the instance to not have any properties and if this happens what we’ll do is we will inherit the property from the main.

Component so now we can infer that the instance has content equals button and so what this means is that instances inherit new changes if they have not been modified so if we change the main component again now because of the inheritance structure when they’re modified this button will also be modified.

But note this is only going to happen if the instance property has not been modified at all so if we have changed the value to say something else we’re actually going to be storing that data explicitly and we’ll store it as content equals favorite and so when the main component updates the instance will retain its.

Value and so these were two possible choices for what a value could represent when we’re assigning values and creating properties on components and we you know really asked ourselves which option should we pursue and there were product and design trade-offs for both options with the initial value approach that.

Would work well work really well with Boolean properties because if you have a Boolean property that’s set to true or false it would be a little bit weird if your values sort of went back to the original value when the main component changes but with default values that works a little bit better for text and instant swap properties especially.

Because that matches the behavior for how overrides work and how overrides are retained on update and so to answer this question we actually ended up diving into a specific engineering Edge case um to figure out you know how uh these trade-offs would work in different cases that users might um fall into.

So this Edge case happens to be around what happens when you update your instances between when we had no props to when we now have introduced the props feature so there’s going to be a conversion process where people are going to be updating their instances to now be using the new design system that has component properties.

And so what’s going to happen is we might create a component with no props we’ll go ahead and create an instance of it and the instance hierarchy might look something like this as we’ve seen before and then we want to override the text button and so now we don’t have props yet so we’re just going to use regular.

Overrides to change the buttons content to say favorite and it’ll look something like this and we’ll be able to render it accordingly now we’ve introduced the props feature and we’re going to be adding a text property to the component so we’re assigning the content property to the value button.

But now what’s going to happen to the instance and its pre-existing overrides well in an initial value world we have this setup we have the button um has an override where the text says favorite and before the update we’ll have this uh favorite override on instance or prop creation we’re going to explicitly assign the value.

So we’ll create the instance and we’ll actually assign that value using the value that we had given when during the prop creation process and that value will be buttoned so because props take precedence over overrides we may lose previous overrides and so what’s going to happen is you might sort of see this change when you.

Update your instance from the texting favorite to the text saying button which is a little unideal so instead we also looked at what would happen if we chose a default value approach well similarly before the update we’ll have the button say favorite and because the value is a fallback when the value is provided when.

We update we’ll actually have like this empty map of properties and the flexibility of The Inheritance model allows us to choose when and where we inherit from so we can choose to inherit from the overrides as opposed to always inheriting from assignments and or from property assignments which is what they call them internally.

Um and this allows us to easily retain overrides on instances when authors add properties and so when you’re converting from instances without props to instances with props we’re able to sort of retain that text property um so this was just one of the edge cases that we had to walk through and we really wanted to pay close attention to.

The details so that our users could have a seamless sort of Design Systems um upgrade experience so after optimizing for all of these different issues and edge cases we finally launched component props version one at config loss year or sorry config this past May um but even after the launch there was.

Still a lot we could do and we got a lot of both external and internal feedback that the consumption experience might still be less than ideal for DS consumers so one of the largest pain points that we hear from people even before we started working on component props was that it’s really difficult for people to navigate these nested layer.

Hierarchies and so even though props help because they indicate which layers can be changed and should be changed um that doesn’t really help a DS consumer if they don’t know which instance to click on in the first place so then over the summer after the config launch we kind of went back to the drawing board and started thinking about.

If there’s any easy wins or fast follows that we could work on to make the lives of DS consumers a lot easier and so with that we launched three new features as part of component properties version two the first one is exposed instances so exposed instances allows you to have a top level instance selected and it’ll.

Automatically show props from not only that instance but also any child instances as well so you don’t have to navigate into the layers panel and click around and guess which instances have those props anymore the second feature we launched is simplified instances so simplified instances just simplifies the layers.

Panel canvas hit targets and also properties panel so only layers with props are shown by default and finally we have preferred values preferred values lets Design Systems authors specify a set of instances that an instance prop can be swapped to and then on the consumption side this makes it a lot easier for DS consumers because.

All of the preferred values live in a single drop down folder so you no longer have to navigate through complicated folder structures in a super small instance bigger and finally all of these features finally launched in an open Beta a couple short weeks ago so we’d love for everyone to try it out if you haven’t.

Already and feel free to send any feedback our way and finally we want to give a big shout out to everyone on the component props team that works super hard on making this feature a reality and also had a ton of fun along the way so thank you to the team and also to our wonderful audience at schema today thank you for.

Joining us

Component properties launched at Config earlier this year, but was over a year in the making. Essentially React properties for …

Figma Official Channel,inside,behind,the,figma, design, product design, tips, tricks, UI design, ux design, app design, figma design, design for figma, FigJam tutorial, prototyping, collaboration, UX tutorial, Design tips, whiteboard, Figma tutorial, Config, Config 2022, design system, tutorial, product:none, audience:designer, language:english, format:standard, produced_by:marketing, theme:design_systems, event:schema, series:none, type:other, level:intermediate, primary_feature:none, secondary_feature:,

Total
0
Shares
Leave a Reply

Your email address will not be published. Required fields are marked *