Finally add custom instance-local state: Prototype conditional action should be able to use boolean and text component properties
Background
People have been begging for local component instance-scoped variables since variables were introduced in 2023. This comes from variables as they are today existing exclusively at the document level, making advanced behavior possible to do once with the global state, but you painfully discover its impossible to package and re-use anything you make that relies on it. All instances have to share the single global state, which directly shatters the fundamental idea that Figma is about making re-usable components that speed up your workflow and maintain SSOT.
Requests differ in their implementation, but the common request is to somehow allow components to define values with at least the same power as the existing variables, only local to each instance of the component. People want to be able to make the same advanced behaviors we already can with global variables, just packaged into a component you can actually instantiate multiple times without side effects.
I’m writing this feature request because to me it looks like the idea always gets put off or ignored because it’s seemed so far away or hard to do, but I want to say and show that’s not the case. There are some very small changes you could make today with big impacts that would start a path towards completely filling the gap as incremental fixes and tweaks, instead of needing deep completely novel features.
Justification/Impacts/Related Threads
Too many to lay out. This is in my opinion, the most fundamental gap between what I think everyone agrees Figma is “supposed” to be able to do, and what it is capable of in reality, but that isn’t the result of a bug. Figma has plenty of major fundamental flaws, I’ve made plenty other comments/posts/support tickets on them, but they have largely been bugs that are obviously unintended behavior. This is an obviously missing behavior, not a bug, and not quite a “feature request”. Components don’t make sense in a system that only lets you have custom state if it’s global, and only allowing custom state to be global doesn’t make sense in a system with components.
Component-owned variables already exist
However you say it, per-instance variables, component-scope variables, custom per-instance state, local variables, etc, the idea already exists and has a name. Component Properties. The Component Property most people are familiar with is the Variant Swap property, but you can also make boolean and string component properties.
The String and Boolean Property
Inside a component definition with a string and boolean property, as long as there isn’t a slot between you and the component/instance root layer, you can bind text string attributes to the component’s string property, and bind layer visibility and anything else that can bind to booleans to the component’s boolean property you made. Then, when you create instances of that component, those properties are exposed to you at the instance’s top level and you can choose to override the default values for each property that was set in the component.
In practice, the boolean and string properties are only useful as a convenience so you can name and show what attributes you are supposed to modify, and so you don’t have to hunt for each layer by hand. Using boolean and string properties is functionally equivalent to just going to the places each property had been bound, and manually make the change there in each instance.
Custom Per-Instance State Already Exists
The Variant Swap Property is a step up from the String and Boolean properties, and demonstrates the next key aspect of this that already exists today. Instances already can have their own per-instance state. For every instance of a component with multiple variants, which variant is currently “active” can be changed dynamically by Prototype Actions in Present/Preview. This is the fundamental behavior that the entire Present/Preview system requires to do even the most basic interactive behaviors. This demonstrates that per-instance state is fundamentally possible already.
What’s missing?
The single difference between the Variant Swap Property and the String and Boolean properties that makes one just a convenience and the other real, powerful local state is that String and Boolean properties are completely invisible to the entire Prototype Interaction system, leaving them “fixed” in Present/Preview, while the Variant Swap can change from Prototype Actions.
Implication
I wonder. If the Variant Swap state is a Component Property, and the String and Boolean Properties are also Component Properties, I wonder if under the hood, it’s actually technically already set up so each instance of a component gets it’s own mutable local instances of those properties. I wonder if the Component Properties other than the Variant Swap Property are already set up as local per-instance state, and we are just missing the Prototype Action hooks to mutate them.
Property <-> Prototype Action Precident
This is the first of those “small incremental steps” I mentioned. At the moment, not only are Prototype Actions unable to set properties besides the Variant Swap, the Conditional Prototype Action also cannot read/evaluate Component Properties. This is the smallest change I could think of that would begin to unlock everything. Start by allowing the Conditional Prototype Action to evaluate Boolean and String Component Properties. This doesn’t need even a single new visual asset or button of any kind, just expose them in the list above the variables when you go to type the expression for a Conditional Action, using the same visual behavior that happens when you bind an attribute to a Component Property. I assume, perhaps naively, that the value of Component Properties are already exposed in a way Prototype Actions should be fundamentally capable of receiving if allowed to.
The next small step is just a tiny bit larger. Add a Number and Color Component Property, implemented simply as copies of how the String and Boolean Component Property works under the hood. That brings the set of types available into parody with the global variables.
After that, though a bit larger, is to add a new Prototype Action that lets interactions modify that instance’s other Component Properties besides just it’s Variant Swap. This could also be pretty much just a copy under the hood of the “change to” Prototype Action, just targeting our other properties.
Conclusion
That’s my proposal. Feature-complete local per-instance variables are, at least to an outsider, only 3 simple extensions of existing features away.
Related Threads
There’s like a million, I’ll try make a follow up post listing them if I remember.
