Skip to main content
Solved

Retrieve color variable name from a node

  • February 4, 2025
  • 5 replies
  • 65 views

Petra_Javorkova1

Dear community, I'm creating a Figma PLUGIN solution that finds all component nodes and filter only those, whose color variable matches a user's input. 

 

Usecase:

  • Designer wants to find where is a specific color variable used within a library file.

 

How it should work:

  • User types in a plugin UI: “button/background/hover”
  • Plugin search through all the component nodes.
  • Plugin prints out all component nodes that have the typed variable in their color fills.

 

Problem:

  • Any component node I retrieve, there is no “boundVariable.fills” available to inspect, so that I cannot think of a proper way how to get to the fills variable.
  • For a context: ComponentNode id: 1:10 (from the screenshot) is paired to a variable color
  • Plugin returns at “if (selectedNode.boundVariables?.fills)”

 

Code

async function findComponentsUsingVariable(typedName: string) {
    try {
        // Ensure that all pages are loaded properly
        console.log("Loading pages...");
        await figma.loadAllPagesAsync();
        console.log("Pages loaded successfully.");
    } catch (error) {
        console.log("Could not load pages asynchronously. Error: " + error);
        return; // Stop execution if loading pages fails
    }

    const components: { id: string; name: string }[] = [];

    // Fetch only components
    for (const page of figma.root.children) {
        const nodes = page.findAll(node => node.type === "COMPONENT" || node.type === "COMPONENT_SET");

        // Loop ensures the asynchronous operations to be awaited
        for (const selectedNode of nodes) {
            console.log(selectedNode)

            if (selectedNode && "boundVariables" in selectedNode) {
                console.log("Bound Variables:", selectedNode.boundVariables);

                if (selectedNode.boundVariables?.fills) {
                    console.log("Fill is bound to a variable.");

                    // Access the first bound fill variable
                    // Is fill really the 1 in an array?
                    const fillBoundVar = selectedNode.boundVariables.fills[0];

                    if (fillBoundVar) {
                        const variableId = fillBoundVar.id;
                        console.log("Variable ID:", variableId);

                        // Retrieve the variable details
                        const colorVariable = await figma.variables.getVariableByIdAsync(variableId);
                        if (colorVariable && colorVariable.name == typedName) {
                            console.log("Variable Name:", colorVariable.name);
                            console.log("Default Value:", colorVariable.valuesByMode);
                            components.push(selectedNode)
                        }
                    }
                } else {
                    console.log("Fills are NOT bound to a variable.");
                }
            } else {
                console.log("No bound variables found for this node.");
            }


        }
    }

    if (components.length > 0) {
        console.log("Matched Components:", components);
        figma.ui.postMessage({ type: "foundComponents", components: components });
        figma.notify(`Found ${components.length} components using "${typedName}"`);
    } else {
        figma.ui.postMessage({ type: "noResults", typedName });
        figma.notify(`No components found using "${typedName.toString}"`);
    }
}


figma.showUI(__html__);

figma.ui.onmessage = async msg => {
    if (msg.type === "findComponentsUsingVariable") {
        await findComponentsUsingVariable(msg.variableName);
    }
};


 

Best answer by Petra_Javorkova1

SOLVED

 

for (const page of figma.root.children) { const nodes = page.findAll(node => node.type === "COMPONENT" || node.type === "COMPONENT_SET");

 

this loop caused a delay in retrieving all bound variables, and

 

const nodes = figma.root.findAll(node => node.type === "COMPONENT" || node.type === "COMPONENT_SET");

 

solved the problem.

 

Thank you Yury for your quick help :) 

View original

5 replies

tank666
  • 4862 replies
  • February 4, 2025

It looks like the variable is not bound to the fill at the ComponentNode level. To verify this, expand the properties of ComponentNode {id: '1:10'} to manually inspect the boundVariables and fills properties, or look in the properties panel in the Figma editor when this node is selected.


Petra_Javorkova1

Thank you Yury, for your quick reply! My node in a file (where I run my plugin) is definitely linked to a color variable, HOWEVER, from an external library (external= outside this file). But this should not be an issue right? 

 


tank666
  • 4862 replies
  • February 4, 2025

Could you send a link to the file with the "Test node" component?


Petra_Javorkova1

Sure, no problem. However, I have just checked how a node is retrieved from a Figma command line (screenshot attached). And actually, the fill array appears! Thats why Im questioning my code, whether its asynchronous call does not wait for the fill to be retrieved in an array…. 

 


Petra_Javorkova1

SOLVED

 

for (const page of figma.root.children) { const nodes = page.findAll(node => node.type === "COMPONENT" || node.type === "COMPONENT_SET");

 

this loop caused a delay in retrieving all bound variables, and

 

const nodes = figma.root.findAll(node => node.type === "COMPONENT" || node.type === "COMPONENT_SET");

 

solved the problem.

 

Thank you Yury for your quick help :) 


Reply


Cookie policy

We use cookies to enhance and personalize your experience. If you accept you agree to our full cookie policy. Learn more about our cookies.

 
Cookie settings