Hello everyone,
I am developing a Figma plugin where I have created a ComponentSet
with two variants. Each variant has a state
and a heading
property. I want to dynamically assign the heading
property to a text node within each variant.
Here is the simplified code for creating the ComponentSet
:
figma.showUI(__html__, {
height: 200,
width: 400,
});
figma.ui.onmessage = async (msg) => {
if (msg.type === 'create-input-field') {
await figma.loadFontAsync({ family: 'Inter', style: 'Regular' });
// Create variants for the component
const defaultComponent = createComponentWithFrame('State=Default');
const filledComponent = createComponentWithFrame('State=Filled');
// Create a component set and add the components as variants
const componentSet = figma.combineAsVariants([defaultComponent, filledComponent], figma.currentPage);
componentSet.name = 'My Component Set';
componentSet.resizeWithoutConstraints(1200, componentSet.height);
componentSet.layoutMode = 'HORIZONTAL';
componentSet.counterAxisSizingMode = 'AUTO';
componentSet.primaryAxisSizingMode = 'AUTO';
componentSet.paddingTop = 20;
componentSet.paddingBottom = 20;
componentSet.paddingLeft = 20;
componentSet.paddingRight = 20;
componentSet.itemSpacing = 18;
componentSet.fills = [];
componentSet.cornerRadius = 5;
componentSet.strokes = [{ type: 'SOLID', color: { r: 0.592, g: 0.278, b: 1.0 } }]; // #9747ff
componentSet.strokeWeight = 1;
componentSet.dashPattern = [10, 5];
componentSet.strokeAlign = 'INSIDE';
componentSet.strokeJoin = 'MITER';
componentSet.strokeMiterLimit = 16;
componentSet.clipsContent = true;
// Position the component set on the canvas
componentSet.x = figma.viewport.center.x - componentSet.width / 2;
componentSet.y = figma.viewport.center.y - componentSet.height / 2;
}
};
const createComponentWithFrame = (variant: string): ComponentNode => {
let color: Paint[] = [{ type: 'SOLID', color: { r: 0.592, g: 0.278, b: 1.0 } }];
switch (variant) {
case 'State=Filled':
color = [{ type: 'SOLID', color: { r: 0.9, g: 0.9, b: 0.9 } }];
break;
default:
color = [{ type: 'SOLID', color: { r: 0.592, g: 0.278, b: 1.0 } }];
break;
}
const component = figma.createComponent();
component.name = variant;
component.layoutMode = 'VERTICAL';
component.fills = color;
component.resizeWithoutConstraints(252, component.height);
component.addComponentProperty('Heading', 'TEXT', '');
setupAutoLayoutAndText(component);
return component;
};
const setupAutoLayoutAndText = (node: BaseFrameMixin): void => {
node.layoutMode = 'VERTICAL';
node.primaryAxisSizingMode = 'AUTO';
node.counterAxisSizingMode = 'AUTO';
node.paddingTop = 0;
node.paddingBottom = 0;
node.paddingLeft = 0;
node.paddingRight = 0;
node.itemSpacing = 4;
const label = figma.createText();
label.characters = 'Label';
label.fontName = { family: 'Inter', style: 'Regular' };
label.lineHeight = {
value: 23,
unit: 'PIXELS',
};
label.letterSpacing = { value: 0, unit: 'PERCENT' };
label.textAlignHorizontal = 'LEFT';
label.textAlignVertical = 'BOTTOM';
label.fontSize = 14;
label.name = 'Label';
const labelContainer = figma.createFrame();
const childContainer = figma.createFrame();
labelContainer.counterAxisAlignItems = 'CENTER';
labelContainer.counterAxisSizingMode = 'AUTO';
labelContainer.primaryAxisAlignItems = 'MIN';
labelContainer.primaryAxisSizingMode = 'FIXED';
labelContainer.fills = [];
labelContainer.strokes = [];
labelContainer.paddingTop = 0;
labelContainer.paddingBottom = 0;
labelContainer.paddingLeft = 0;
labelContainer.paddingRight = 0;
labelContainer.itemSpacing = 4;
labelContainer.clipsContent = false;
labelContainer.layoutAlign = 'STRETCH';
labelContainer.layoutGrow = 0;
labelContainer.layoutMode = 'HORIZONTAL';
labelContainer.layoutGrids = [];
labelContainer.layoutPositioning = 'AUTO';
labelContainer.appendChild(label);
node.appendChild(labelContainer);
node.appendChild(childContainer);
};
I am looking to understand how I can link the heading
property to the text node so that changes to the property reflect in the text content.
Any guidance or examples on how to achieve this would be greatly appreciated.
Thank you!