Using components from a design library file within a plugin
I’ve seen a bunch of threads just like what I’m about ask so sorry for the repeat question. I’ve tried everything I read in the other threads and I still can’t create instances of the component in a file outside of the design library.
What I’m trying to achieve is based on the selection made it generates a specific component.
The file that I am linking to is a published design library and I have the key and the component set ID
However, I continue to get this error state in the console
unhandled promise rejection: Throw: Failed to import component set by key ""
You need to import a specific component set, not the whole library file. And it’s done by component set KEY, not ID.
In general plugins don’t have access to file keys — unless it’s a private plugin but in that case the key is not used in the plugin context, it’s used to communicate with the REST API.
All of the console.log messages print correctly so I think all the logic is correct. But when I try to create an instance of any of these I get the error
[symbol] failed to repair styles
Uncaught (in promise) TypeError: Cannot read properties of null (reading 'defaultVariant')
@Gleb would you be able to provide any additional help here?
Are you trying to grab a component from the library or the whole library?
If you are trying to grab a specific component from a library you can use this code after you get the component key from the console:
in Figma go to your component and select it, go to Plugins >>Development>>Open Console and paste the following code in at the console prompt and it will return your component key:
figma.currentPage.selection[0].key
Copy the key and replace this text - [insert component key here] - in the code below and use that in your plugin.
async function importNode() {
let importComponent = await figma.importComponentByKeyAsync("[insert component key here]");
let instance = importComponent.createInstance();
await figma.currentPage.appendChild(instance);
}
importNode();
You are getting an error in this line. You already imported the component (componentSet) and you are trying to search for it inside of itself. So you are getting undefined as a component set doesn’t (and can’t) contain any other component sets. Just delete these lines and rename componentSet (after then) to cartComponentSet.
Be careful with using type assertions like as ComponentSetNode. As you can see it made TypeScript believe everything is fine as you told it you know that you will be getting a component set but that wasn’t the case when running the code.
Also instead of using cardComponentSet.findOne it’s better to use cardComponentSet.children.find(n => n.name === 'Property 1=Cart M2') as this would already give you the correct type (no need for type assertion and checking the type — component set can only contain component nodes). Plus it won’t search the whole tree of the component set contents which is very slow and unnecessary.
No. You still won’t be using the file key in this context and there is no possibility to import the whole library at once — you need to import components and component sets by keys individually if you need any additional ones to the one you are using here.
Note that while the function @Banry_Lincoln_Frisco provided is correct, it only works to import a singular component, not a component set (variant set). Also you don’t need to await the appendChild method result as it’s a synchronous function, plus you don’t need this line in the function at all as createInstance method already places an instance on the current page.
@Gleb good to know. I am successfully importing a component set but… I just noticed, it is contained within a component. This may be the source of another issue. LOL
I have finished my initial plugin that retrieves and places a specific Component Set (name: ‘Cover’) from my team library with the selected variant and data from the UI. (The ‘Cover’ component set has variants for the status of the project, like ‘In Progress’ & ‘Done’. When the ‘Cover’ is initially placed the user selects a “Status” from a dropdown menu and then that instance of the ‘Cover’ is placed)
I have now modified the plugin to first check and see if the component (‘Cover’) is on the page. If ‘Cover’ exists on the page it is selected and then it gets all the data from the nodes to repopulate the UI so the user can update the ‘Cover’ data.
I am able to place a new instance with the updated info but I am unable to change the instance of the existing component on the page.
After selecting the current instance, lets say the current instance has the project status set to ‘In Progress’, of the component set how do I change it to "Done’?
THANK YOU! Let me give that a try.
I hadn’t even considered that. I am a designer not a developer. lol
I’ll let you know if that works. 🙂
So when I check ID’s of the different instances from the placed component (not the original) from the Figma console using figma.currentPage.selectiono0].id i get the same is ‘71:362’ for each one. And these ID’s are different from the original?
should be suffixed with ‘#’ and a unique ID for ‘TEXT’, ‘BOOLEAN’, and ‘INSTANCE_SWAP’ properties
This is not the ID you can get with node.id. This is the ID of the property of the component, which is contained in the name of this property. That is, it exists in the property name, and nothing needs to be added.
And, as you may have noticed, the ‘VARIANT’ type is not specified.
Yes, that’s how it is for the ‘VARIANT’ type. Just don’t forget to add a closing quote (apostrophe) for the value.
I am still missing something, I did add the '.
I was able to get the componentPropertyDefintions when I run the plug in and place the Instance. They are as follows:
Definitions
{Project Status: {…}}
Project Status:
1. defaultValue: "In Progress"
2. type: "VARIANT"
3. variantOptions: Array(6)
console.log('Status to be set:', selectedVariant.name);
if (selectedVariant) {
const instance = selectedVariant.createInstance();
console.log('Instance:', instance.name);
const coverComponent = instance
if (coverComponent) {
figma.currentPage.selection = scoverComponent];
figma.viewport.scrollAndZoomIntoView(ocoverComponent]);
}
--- minus a chunk ---
figma.currentPage.appendChild(instance);
}
figma.closePlugin();
}
In the code I am using to update the component I check to see if the ‘Cover’ instance is there and then retrieve data from the Text Nodes to re-populate the UI where the user puts in the various points of info. The only thing not working is changing the current instance of the ‘Cover’.
This is what the ‘Done’ variant looks like:
Here are the Figma layers:
I am guessing I am on my own now, I am sure that this data I have provided isn’t enough. lol
Using this code I am returning the current variant successfully, but it is not finding any of the other variantOptions: