From c05a5596aaf0778d18469c18e01deb8112169c9d Mon Sep 17 00:00:00 2001 From: Danila Poyarkov Date: Wed, 19 Aug 2026 17:14:24 +0300 Subject: [PATCH] fix(tools): require sibling variant components - Reject combine_as_variants inputs that span different parents\n- Preserve all source components when validation fails\n- Cover the tool-level error path --- packages/core/src/tools/create/components.ts | 3 +++ tests/engine/tools/create.test.ts | 20 ++++++++++++++++++++ 2 files changed, 23 insertions(+) diff --git a/packages/core/src/tools/create/components.ts b/packages/core/src/tools/create/components.ts index 459bbe7b9..c91bfe898 100644 --- a/packages/core/src/tools/create/components.ts +++ b/packages/core/src/tools/create/components.ts @@ -52,6 +52,9 @@ export const combineAsVariants = defineTool({ return { error: 'combineAsVariants requires COMPONENT nodes' } } const parent = nodes[0].parent ?? figma.currentPage + if (!nodes.every((node) => node.parent?.id === parent.id)) { + return { error: 'combineAsVariants requires components to share a parent' } + } try { const componentSet = figma.combineAsVariants(nodes, parent) return nodeSummary(componentSet) diff --git a/tests/engine/tools/create.test.ts b/tests/engine/tools/create.test.ts index 0f115ceca..c9635a1a2 100644 --- a/tests/engine/tools/create.test.ts +++ b/tests/engine/tools/create.test.ts @@ -64,6 +64,26 @@ describe('create_shape', () => { }) }) +describe('combine_as_variants', () => { + test('rejects components from different parents', () => { + const { figma } = setupToolTest() + const firstParent = figma.createFrame() + const secondParent = figma.createFrame() + const first = figma.createComponent() + const second = figma.createComponent() + firstParent.appendChild(first) + secondParent.appendChild(second) + + const result = getTool('combine_as_variants').execute(figma, { + ids: [first.id, second.id] + }) as ToolResult + + expect(result.error).toBe('combineAsVariants requires components to share a parent') + expect(first.parent?.id).toBe(firstParent.id) + expect(second.parent?.id).toBe(secondParent.id) + }) +}) + describe('render', () => { test('renders JSX string', async () => { const { figma } = setupToolTest()