Skip to main content
XavierV
Active Member
September 4, 2023

Create variable in component scope

  • September 4, 2023
  • 9 replies
  • 1052 views

Hello,

It would be more than interesting to be able to create variable at a component scope. And of course instance to inherit those variables.

Why ?

  • it would be a good way to organize variables. One file can have a lot of different components and subcomponents = a lot of variables.
  • it would give us the possibility to ease prototype creation by preparing upfront variables in components library.
  • it is a good way to get rid of variants. I mean variants are nice but variables are far better :).
  • it would give the possibility to create different set of variables corresponding to different state of the components faster.

9 replies

Brad_Zupancic
New Member
October 24, 2023

Is this the type of solution you are looking for?

Don
May 24, 2024

Your proposal is a good addition, but we need scope on file, section, and instance level.

Section prevents everything breaking when you move things between files, but it doesn’t address the component-level issue. Let’s say you make a counter component like this:

( - 0 + )

Each instance needs its own copy of the component’s counter number variable or it breaks. If I make a screen with four separate counters on it, I need to manually make four number variables and wire them all separately. It’s extremely messy and inefficient.

The ideal solution is to expose component properties to the logic system. The only needed change is to allow one boolean property to be used in multiple places in a component with positive and negative checks (show if logged in vs. show if not logged in).

As a side-effect, this would make variable organization much simpler.

Thomas_Klepl
New Participant
November 1, 2024

Yeah I could use this, like today.

I want to have several instances of a component, each with their own separate variable instance values so I can manage logic and state for each instance independently of each other.

hefler
New Participant
March 7, 2025

+1

Time for Variables 2.0!

Ethan C Fisher
New Member
April 22, 2025

+1

also the removal of FigPals is considerably contributing to an increase in my levels of depression 0/10.

Onno_Willems
New Participant
May 1, 2025

I would love this too. For complex components where there is just a minor difference between 2 variants, it would be so nice to be able to remove that variant and bind the change to component variable.

Ryan_Brown1
New Participant
August 21, 2026

+1

 

PLEASE can we get this feature implemented? 

Lucas West
New Participant
September 11, 2026

Please please please fix this missing functionality, I am begging. I swear, this is the only fundamental limitation of the Figma engine I have ever encountered in the last 8 years I have been using it that has yet to be fixed or circumvented to this day. I understand that there could possibly be some underlying architectural challenge or significant design involved with adding this as a complete variables or properties overhaul, however, one thing I think this thread may have overlooked is that the system is actually already 99% there using variable modes, or even completely there if you ignore Prototype interactions.

For anyone who is trying to do this but who doesn't need Prototype interactivity isolated to each instance, (and who isn't on free tier which doesn't get variable modes,) it's possible using manually applied scoped variable modes.

1: Scoped Variable Modes: Variable modes can already be manually applied to a scope, effecting it and any of it's children, and even their children, all the way down. Scoped variable modes can be applied to a scope from the header of the Appearance section in the right sidebar when a frame or instance of a component is selected, using the button that looks like paint swatches. 

2: Bind Variant Swap to Variable: Instances can already have their variant property(s) bound to existing string or boolean variables. If you make a string variable with multiple modes each containing the exact name of one of your variants, then instances of your component can bind their active variant name property to that string variable. If you then change the mode of the string variable's variable collection, the instance's variant will update accordingly. Creating this binding can be done using a button hidden to the right of the variant dropdown at the top of the right sidebar that only appears on hover when an instance of a component with multiple variants is selected.

3: Prototype Interactions: Prototype interactions can already change the current global variable mode of a variable collection. You can use this to, for example, make a button that changes the global color theme mode from light to dark when pressed in Preview or Present.

With the first two things, everything wanted here can be achieved, but only if you are willing to give up Prototype interactions.

If you do need Prototype interactions, you are out of luck as scoped, non-global/per-instance variable modes can currently only be applied manually. Prototype interactions cannot apply or even modify scoped variable modes. The "Set variable mode" Action modifies only the global variable mode, even when executed from somewhere, or from inside somewhere, with a scoped variable mode set.

This tiny discrepancy makes this almost look like a bug or an oversight as supposed to a completely overlooked or missing feature. This gap could be closed simply by making the "Set variable mode" Prototype interaction target it's closest parent that sets that variable mode, and only hits the global variable mode if it finds no such parent.

If it was just that, I would still just call it a missing feature. To an outsider it looks like something that would need some amount of engineering work to add to the system. Perhaps the Prototype interaction system is fairly separate, and doesn't currently have any means to take in or interact with scoped variable modes. However, this is demonstrably not the case.

Say you have a component. If you give it an interaction with "Conditional" as it's Action, you are able to evaluate the current state of a variable in the Condition. Since the "Set variable mode" action doesn't see scoped variable modes, one would expect that the Condition in the "Conditional" action would also similarly evaluate variables according to it's global variable mode. This is not the case. The Condition in "Conditional" DOES account for it's current scoped variable mode.

A setup demonstrating this behavior can be assembled by doing the following:

1: Make a component with two states, like a switch. Don't wire up any interactivity.
2: Place an instance of your switch inside a new component, the wrapper.
3: Place an instance of the wrapper inside a new, third component, the root.
4: Set up a new variable collection with a string variable and two modes, off and on. Put in the exact names of the switch's off and on variants in the off and on modes for that string variable.
5: Go to the wrapper component declaration, select the instance of the switch component, and then press the hidden button to the right of the instance's variant dropdown. Select the string variable from step 4.
6: Go to the root component declaration. Give it a Prototype interaction on click which uses the Conditional action to check the string variable, and then set the string variable to it's inverse.
7: Create 3 instances of the root component.
8: Set the variable mode of the first instance to either mode. Leave the other two instances unset, aka auto mode.

If you followed along, just play with the three of them in preview or present and it will be clear.

Otherwise, the following is what you would see when trying them individually:

- Clicking the switch with the set mode fails to change itself as discussed.
- Clicking one of the other two switches toggles itself.

This implies that setting a scoped variable mode just breaks interactions involving the variable mode.

The following is what you would see when trying the three of them on one screen all together at once:

- Pressing either of the two unset switches toggles the both of them in unison. They share the global variable mode, this makes sense. The set switch is logically unaffected, it stays frozen on the state it's scoped variable mode was set to.
- If you start with the fixed switch set to the OPPOSITE mode as the global variable mode and you click the fixed switch, nothing happens. This also makes sense under the assumption that interactions inside variable mode scopes don't work.
- However, if you start with the fixed switch set to the SAME mode as the global variable mode, such that it matches the other two switches, and you press it, you will notice that the two unset switches DO flip.

This demonstrate that the Prototype system both DOES see scoped variable modes when evaluating the conditional, but that it also DOESN'T see scoped variables at all when it goes to set it.

 

TLDR: read-only non-interactive scoped boolean or enum type variables currently CAN be achieved, scoped to individual component instances, using manually applied scoped variable modes. However, even if interaction were fixed as outlined in this post, for some applications this is still a fairly clumsy, roundabout workflow. It’s also restricted to non-free tiers, and requires the creation of new variable collections with sometimes only a single variable in each, for every new state you want to have. It’s actually a pretty clean system for my own workflow, but for other people’s use cases who are looking for local variables, it's important to mention that this only works for things with a concrete number of states, IE, booleans or enums (a string with a mode for each option it could be), and is completely useless if you want to be able to put in numbers or colors or anything else, though that can also already be somewhat achieved with the “Expose properties from: Nested Instances” option when creating a new property in a component.

My use case: This would allow component libraries in design systems to build up their controls out of shared primitives. The top-most objects would collect the different types of interactions and set variables for each, and then the children of those objects could just subscribe to that variable and receive changes through it. Since the variable modes are defined globally but would potentially be overridden in a specific instance through it's scoped variable mode, all the primitive component declarations could subscribe to those variable modes globally in their definition, but then automatically inherit things like hover state or pressing state or primary vs secondary coloring, for example, from the local state of any enclosing instance in a straight-forwards manner.

 

Lucas West
New Participant
September 14, 2026

Edit: I forgot to mention that you can also just combine this technique (variants of children bound to local variable modes set by an ancestor) with variants on the root component to make this work completely. Just make variants each specifying one of the possible modes, then you can use the prototype interactions to swap between those variants to sort of indirectly change the set local variable mode for the root component. This way, children can still just subscribe to that variable mode and receive local, instance-specific variable state.

This is a good work-around that I will be using, but it is more annoying than just having the interaction swap the variable mode itself. This workaround also unfortunately doesn’t let interactions on deep children change the local variable mode that one of it’s ancestor’s has set, as the proper fix described above would.

Both this workaround, and also potentially the minimum viable fix described above, may have hit-or-miss animation/transition support. From my rudimentary tests, smart animate seems to work fairly well for simple color changes with only slight layout wiggling, but I could see more complex interactions becoming complicated.