Die Oberfläche ist lokalisiert; Skill-Beschreibungen und -Dokumente werden per KI automatisch in Ihre Sprache übersetzt. Code, Befehle, Pfade und Fachbegriffe bleiben im Original, maßgeblich ist das Dokument des Autors.
Skills entdecken
Design und Kreativität · SKILL.md

figma-click-flow

figma-click-flow

Draws a click-flow overlay on a section of laid-out Figma screens for static handoff: a dot on each clickable element, an elbow line with rounded corners and an open arrow at the destination screen. figma.createConnector is not a function in Figma Design files, so each connector is emulated with one SVG import (hardened recipe in references/draw-overlay.js)…

Independent GitHub snapshot · Automated classification · Original documentation governs

Skill-Dokumentation

GitHub

name: figma-click-flow description: >- Draws a click-flow overlay on a section of laid-out Figma screens for static handoff: a dot on each clickable element, an elbow line with rounded corners and an open arrow at the destination screen. figma.createConnector is not a function in Figma Design files, so each connector is emulated with one SVG import (hardened recipe in references/draw-overlay.js). Use when the user asks for a "click flow", "flow arrows", "wire screens", "turn this into a flow", or in Portuguese "vira em fluxo", "setas do fluxo". license: MIT compatibility: >- Writes to a Figma Design file through figma-console-mcp (figma_execute, Desktop Bridge plugin in Figma Desktop) or through the official Figma MCP server (use_figma, Full seat, not validated by this repo; the recipe guards figma.loadAllPagesAsync, which Figma lists as not implemented there). Requires the figma-canon and figma-preflight skills. metadata: author: Thiago Xikota version: "1.2.0"

figma-click-flow: Click-flow handoff overlay

Draws a printed user-flow overlay on a section of laid-out screens. Each connection: a red dot at the click target on screen A, an elbow line with rounded corners ending in an open arrow at screen B's nearest edge. Reference look: a flow section of one production file.

REQUIRED PREREQUISITE: load figma-canon + pass figma-preflight before any figma_execute write (the write path is the figma-console MCP server through its Desktop Bridge plugin). With only the official Figma MCP server connected, the write goes through use_figma on path B of figma-preflight Check 0 (not validated by this repo: keep writes small, read back every change), and Phase 4 validates with get_screenshot within the budget in figma-canon/references/rate-limit-recovery.md.

Why a separate skill (not createConnector)

figma.createConnector throws not a function in Figma Design files (verified via figma_execute, field note 2026-05). CONNECTOR nodes that already exist in design files were created via the UI (Shift+L shortcut) and cannot be cloned: node.clone() errors with Cloning CONNECTOR nodes is not supported in the current editor. This skill therefore emulates the connector look by importing one SVG per connection through figma.createNodeFromSvg.

When to use

  • A section of screens is already laid out and the user wants the printed click-flow overlay on top.
  • The designer wired the prototype (reactions on nodes) and wants the same connections visible in static handoff.
  • The user provides explicit (from-element-id -> to-screen-id) pairs.

When NOT to use

  • File is FigJam: use figma.createConnector directly.
  • User wants to design layout: use your project's own build skill or workflow, if any, or ad-hoc figma_execute after figma-preflight.
  • User wants Dev Mode component documentation: out of scope for this skill. Use your project's own handoff documentation workflow, if any.
  • Section has > 40 connections: output becomes spaghetti. Split into smaller sub-sections first.

Visual canon

Verified against a reference node in one production file. refConn in the right column is the reference connector.

PropertyValueSource of truth
Stroke color#E5484DNeutral default, configurable. The reference used one dominant red in 20+ instances; that value was project-specific
Stroke weight4 pxrefConn.strokeWeight === 4
PathElbow with rounded corners, R = 12 pxconnectorLineType: 'ELBOWED' + visual radius pixel-picked
Origin markerFilled circle, r = 5 px (10 px diameter)connectorStartStrokeCap: 'CIRCLE_FILLED'
End capOpen arrow, two strokes back from tip at ±28°, length 12 pxconnectorEndStrokeCap: 'ARROW_LINES'
Layer nameflow-overlay · click-connectors (kebab-case with a middle-dot separator, from one project's own layer canon; keep this exact name, because the rerun and the cleanup snippet find the overlay by it)figma-canon/references/naming-canon.md

The stroke color #E5484D is a neutral default and is configurable: override it through the strokeColor input (STROKE_COLOR in the recipe) when the file has a brand-specific accent.

Inputs

sectionId: "123:456"            # required
mode: from-prototype            # default; OR "explicit" OR "auto-layout"
pairs:                          # used when mode === "explicit"
  - from: "123:789"             # element that gets tapped
    to:   "123:790"             # destination screen
triggerFilter: ["ON_CLICK", "ON_PRESS"]   # default; ignores hover/drag
includeOverlayActions: true     # default; sheets count as navigation
strokeColor: "#E5484D"          # default; see Visual canon
cornerRadius: 12                # default
strokeWeight: 4                 # default
originAnchor: "auto"            # default; "center" | "edge-toward-dest" | "auto"

Each input is a constant in the CONFIG block of references/draw-overlay.js: sectionId is SECTION_ID, mode is MODE, pairs is EXPLICIT_PAIRS, triggerFilter is TRIGGER_FILTER, includeOverlayActions is INCLUDE_OVERLAY_ACTIONS, strokeColor is STROKE_COLOR, cornerRadius is CORNER_RADIUS, strokeWeight is STROKE_WEIGHT, originAnchor is ORIGIN_ANCHOR. The recipe also has DOT_RADIUS, ARROW_LEN, AUTO_LAYOUT_MIN_AR and AUTO_LAYOUT_ROW_GAP, which have no input above.

mode reference:

  • from-prototype (default): walks reactions[] on every descendant. Best when designer wired the prototype.
  • explicit: uses pairs. Best when the caller has a known list (from a PRD, a spec that lists screen transitions, or a hand-curated list).
  • auto-layout: groups top-level FRAMEs in the section into rows by Y, sorts each row by X, builds intra-row left-to-right pairs. Best when prototype isn't wired and screens are sequentially laid out (like a numbered catalog). Heuristic: verify visually before trusting; rows mixing scenarios may produce wrong connectors.
    • The name means pairs inferred automatically from the layout. It has nothing to do with Figma's Auto Layout feature.
    • Only portrait children count as screens: FRAME, COMPONENT or INSTANCE with height/width >= 1.3 (AUTO_LAYOUT_MIN_AR). This filters out labels and dividers. For desktop or landscape screens, lower that constant, or the run returns drawn: 0.
    • A screen whose Y is more than 100 px (AUTO_LAYOUT_ROW_GAP) below the previous one starts a new row.

originAnchor reference:

  • auto (default): bbox center for small nodes (<200×200 = buttons, list rows), edge-toward-dest for screen-sized nodes (any node at least 200 px in both dimensions). Right behavior for both prototype-driven mode and screen-level adjacency.
  • center: always bbox center. Use when prototype reactions are wired on small interactive elements and you want the dot ON the button.
  • edge-toward-dest: nearest-edge midpoint. Use for screen-to-screen adjacency where center would put the dot deep inside the screen body.

If user just says "wire it up" with no detail, default to mode: from-prototype.

Workflow (4 phases + cleanup)

Phase 0: Sanity

Walk up to the page ancestor (sections may be nested inside sections), call figma.loadAllPagesAsync(), then await figma.setCurrentPageAsync(pageNode). Use figma.getNodeByIdAsync exclusively: sync getNodeById errors under documentAccess: dynamic-page.

Server note for use_figma (official Figma MCP server): Figma's figma-use skill lists figma.loadAllPagesAsync() as not implemented in that runtime, and says a read of a member the node type does not have throws TypeError: node.X: no such property 'X' on Y node, optional chaining included (figma/mcp-server-guide, read 2026-10). So the recipe calls figma.loadAllPagesAsync() inside try/catch and carries on without it (setCurrentPageAsync loads the page anyway), and it checks "reactions" in n before reading reactions, because SECTION, SLICE and COMPONENT_SET nodes do not declare it. In figma_execute both guards change nothing. This repo has not run the recipe on use_figma.

Phase 1: Discover pairs

Walk descendants of the section. For each node, inspect reactions[], and in each reaction read actions[] (the recipe falls back to the singular action field when actions is absent). Collect a pair when:

  • action.type === 'NODE' (navigate to frame), OR
  • action.type === 'OVERLAY' (open sheet/modal, counts as flow), AND
  • reaction.trigger.type is in the triggerFilter (default: ON_CLICK, ON_PRESS, ON_TAP).

The recipe keeps a reaction that has no trigger.

Drop pairs where from or to cannot be resolved or lies outside the section's bounding box (likely external/cross-page links). Dropped pairs come back in the dropped array of the return value with a reason (node not found or outside section): report them instead of losing them silently.

If 0 pairs found, return early with a warning so the caller can switch to mode: explicit and supply pairs manually.

Phase 2: Plan elbow geometry

For each pair compute (all in absolute page space):

  • origin = anchor on from node's absoluteBoundingBox, picked by originAnchor: bbox center for small interactive nodes, nearest-edge-toward-dest for screen-sized FRAMEs (auto default), or as overridden.
  • dest = nearest-edge midpoint of to frame's absoluteBoundingBox (left / right / top / bottom).
  • Routing: a single L-shape through (midX, origin.y) then (midX, dest.y) where midX = (origin.x + dest.x) / 2. Same right-angle topology as connectorLineType: 'ELBOWED'.
  • Corner radius = cornerRadius (default 12), inserted as Q-curves.

If |origin.y - dest.y| < 2 * cornerRadius, drop the elbow and draw a straight line (avoids degenerate corners).

Phase 3: Draw

Per pair, build an SVG string with:

  • <circle> at origin (origin marker).
  • <path> with the elbow + Q-corners (the trunk).
  • <polyline> arrowhead at dest.

Import via figma.createNodeFromSvg(svgString), which returns a FRAME with vector children. Position the imported frame at (minX, minY) (the SVG's top-left in page space).

Coord-space rule (verified): SECTION children use section-local coords. After section.appendChild(overlay), set overlay.x = 0; overlay.y = 0 so overlay aligns with section's top-left. Then position each imported SVG frame as a child of overlay using overlay-local coords (subtract section absolute origin).

vectorPaths.windingRule: 'NONE' is accepted by the API (verified). Auto-fit moves a vector to its path's leftmost coord after vectorPaths is set; trust this rather than fighting it.

See references/draw-overlay.js for the complete hardened snippet. The same snippet is written to run in use_figma of the official Figma MCP server too, with the guards described in Phase 0 (not validated on that server by this repo); the timeout figures below are for figma_execute only.

figma_execute has a default timeout of 5000 ms and accepts up to 30000 ms. After a timeout or an error, do not rerun at once: this recipe removes the prior overlay and then draws a new one, so first read figma-canon/references/figma-execute-atomicity.md and the section "figma_execute timeout on bulk clone and font loads" in figma-canon/references/plugin-api-anomalies.md.

Phase 4: Validate

Use figma_capture_screenshot (plugin export). REST-backed screenshots return HTTP 429 (rate limited) after a handful of calls in a batch; see figma-canon/references/rate-limit-recovery.md. Do not use figma_take_screenshot for large sections.

As of figma-console-mcp v1.40.8, figma_take_screenshot uses the Desktop Bridge plugin when connected and falls back to the REST API, while figma_capture_screenshot always uses the plugin runtime and needs the bridge. The rule above still holds: figma_capture_screenshot is the call that always stays on the plugin runtime.

Check:

  • Every line starts on a real interactive element, not whitespace.
  • Lines do not cut through unrelated screens (if so, raise corner radius or split into sub-sections).
  • Origin dots sit on the correct element.
  • Color, stroke weight, dot size match the visual canon table.

Cleanup / remove overlay

Idempotent rerun: skill auto-removes any prior flow-overlay · click-connectors frame inside the section before drawing. To remove without redrawing (here section is the section node, from await figma.getNodeByIdAsync(sectionId)):

const overlay = section.findOne(n => n.name === 'flow-overlay · click-connectors');
if (overlay) overlay.remove();

Common mistakes

MistakeFix
figma.createConnector(...)Not a function in design files; emulate via SVG import
node.clone() on existing CONNECTORThrows "Cloning CONNECTOR nodes is not supported"
figma.getNodeByIdUse getNodeByIdAsync; sync version errors under dynamic-page
Set overlay.x = section.x before appendSection children use LOCAL coords, produces double offset; set x=0; y=0 AFTER append
Validate with a REST-backed screenshotfigma_take_screenshot returned 429 on the large sections of one production file; use figma_capture_screenshot
Filter only action.type === 'NODE'Misses OVERLAY (sheet open), common in mobile flows; include both
Ignore reaction.trigger.typeHover/drag triggers pollute the overlay; filter to ON_CLICK/ON_PRESS/ON_TAP
Draw nothing when prototype unwiredDetect 0 pairs and return early with a warning, not a silent empty overlay
Sharp 90° cornersUse Q-curves with R=12 to match reference rounded look
Passing section.parent to figma.setCurrentPageAsyncWalk up parent chain until type === 'PAGE'; nested sections break naive section.parent

Quick reference

NeedCall
Discover prototype reactionsnode.reactions[].action.{type:'NODE'|'OVERLAY', destinationId} (the recipe reads actions[] and falls back to action)
Filter by trigger['ON_CLICK','ON_PRESS','ON_TAP'].includes(reaction.trigger?.type)
Build connector SVG<circle> + <path> (elbow w/ Q-corners) + <polyline> arrow
Import SVGfigma.createNodeFromSvg(svgString) returns a FRAME with VECTOR children
Default red#E5484D (rgb 0.898, 0.282, 0.302)
Cleanupsection.findOne(n => n.name === 'flow-overlay · click-connectors')?.remove()

Cross-references

  • figma-canon + figma-preflight: required before any figma_execute write.
  • figma-orient: only run if file is unfamiliar this session; skip otherwise.
  • references/draw-overlay.js: full hardened snippet, copy + parameterize for use. It is a figma_execute body (top-level await and return), not a standalone Node script.
  • figma-canon/references/figma-execute-atomicity.md: what to do after a figma_execute timeout or error before retrying.
Gespeicherte Skills