feat: add component, variant, and prototype reaction tools - #48
feat: add component, variant, and prototype reaction tools#48phss-henrique wants to merge 1 commit into
Conversation
Adds three tools covering Plugin API surface the bridge did not expose: - create_component_from_node: converts an existing frame into a real Component in place via figma.createComponentFromNode. Returns the new node id, since converting changes it. - combine_as_variants: combines Components into a Component Set via figma.combineAsVariants. Figma stacks the children at (0,0), so this lays them out along a configurable axis/gap and resizes the set to fit. - set_reactions: sets prototype reactions (on-click/on-hover navigation) via setReactionsAsync, which is required because the plugin manifest uses documentAccess: dynamic-page, making .reactions read-only. All three are registered in EDIT_REQUEST_TYPES so they respect the existing Dev Mode read-only guard.
|
|
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (4)
Included review availability: Your plan provides up to 4 included reviews per hour; 3 remain after this review. 📝 WalkthroughWalkthroughChangesThe PR adds MCP tools and plugin handlers for creating components, combining components into variants, and replacing prototype reactions. The new mutations use schema validation and are restricted to editor mode. Component and reaction mutations
Estimated code review effort: 4 (Complex) | ~45 minutes Merge Risk: 🔵 Low · up to The new tools enable component conversion, variant-set creation, layout changes, and full prototype-reaction replacement. A timeout or partial variant-layout failure could leave the document in an ambiguous state, and malformed reaction inputs may fail only at runtime. The PR is mergeable with explicit owner awareness and follow-up on mutation recovery and reaction schemas. Sequence Diagram(s)sequenceDiagram
participant MCPClient
participant ServerTools
participant RPCMapper
participant Plugin
participant FigmaEditor
MCPClient->>ServerTools: call component or reaction mutation
ServerTools->>RPCMapper: validate and map arguments
RPCMapper->>Plugin: send editor mutation request
Plugin->>FigmaEditor: create, combine, or update nodes
FigmaEditor-->>Plugin: return node details or reaction count
Plugin-->>MCPClient: return mutation result
Suggested reviewers: 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Pull request overview
This PR expands the bridge’s exposed Figma Plugin API surface by adding three new editing tools: converting nodes into Components, combining Components into Variant sets, and setting prototype reactions.
Changes:
- Registers
create_component_from_node,combine_as_variants, andset_reactionsas server tools and wires them through RPC. - Adds Zod input schemas and RPC argument mapping for the new tools.
- Implements the corresponding plugin-side request handlers and includes them in the edit-mode (non–Dev Mode) guard.
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
server/src/tools.ts |
Registers the three new tools and forwards calls to the plugin via RPC. |
server/src/schema.ts |
Adds input schemas for the new tools and maps RPC wire format to tool args. |
plugin/src/ui/App.tsx |
Extends the UI-side RequestType union to include the new tool request types. |
plugin/src/main/code.ts |
Adds edit-guard coverage and implements handlers for component creation, variant combining, and reaction setting. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
| const node = await getSceneNodeById(nodeId); | ||
| if (node.type === "COMPONENT" || node.type === "COMPONENT_SET") { | ||
| throw new Error(`Node is already a ${node.type}: ${nodeId}`); | ||
| } | ||
|
|
||
| const component = figma.createComponentFromNode(node); |
| const setWidth = layout === "ROW" ? cursor + 40 : maxCross + 40; | ||
| const setHeight = layout === "ROW" ? maxCross + 40 : cursor + 40; | ||
| set.resizeWithoutConstraints(Math.max(setWidth, 1), Math.max(setHeight, 1)); |
|
Hey @phss-henrique before I dive into the code could you sign the CLA? 🙏 |
Adds three tools covering Plugin API surface the bridge doesn't currently expose: creating real Components, combining them into Variant sets, and setting prototype reactions.
I hit these gaps building a multi-screen prototype through the bridge — frames could be created and styled, but there was no way to promote them to Components or wire up click-through navigation without dropping out to the Figma UI.
Tools
create_component_from_node— converts an existing frame into a Component in place viafigma.createComponentFromNode. Returns the new node id, since conversion changes it.combine_as_variants— combines Components into a Component Set viafigma.combineAsVariants. Figma stacks the children at (0,0), so this lays them out along a configurable axis/gap and resizes the set to fit.set_reactions— sets prototype reactions (on-click / on-hover navigation) viasetReactionsAsync, which is required rather than the.reactionssetter because the manifest usesdocumentAccess: "dynamic-page".All three are registered in
EDIT_REQUEST_TYPES, so they respect the existing Dev Mode read-only guard.Testing
No automated tests, since the repo doesn't have a suite. Verified manually against a real file: converted 9 screens to Components and applied 54 navigation reactions across them, with every call accepted by Figma's own destination validation (which does reject invalid targets — it caught a Component Set destination during development). Both
serverandpluginbuild clean.Two things I'd like your call on
set_reactionstakes the reactions array untyped (z.array(z.record(z.unknown())), passed straight through tosetReactionsAsync). It works, but callers get no schema help and only find out about a malformedTrigger/Actionfrom Figma's runtime error. Happy to write proper Zod schemas for the reaction shapes if you'd prefer that.combine_as_variantsdoes opinionated layout. Laying out the children and resizing the set isn't strictly part of the API call — without it you get an unreadable pile at (0,0) — but it is a product decision rather than a thin wrapper. Easy to drop or put behind a flag if you'd rather keep it neutral.Summary by CodeRabbit