Skip to content
Beta Multi-model support (OpenAI, Gemini, and more) launching soon.

figma-component-scaffold

Installable Ships in design-to-code-builder — or copy the raw skill below.
Open Claude.ai

Paste into Claude Code, Claude.ai, the desktop app, or the browser extension — ⌘/Ctrl+V.

ExperimentalNo security review

Figma Component Scaffold

Generate a production-ready, accessible component from a Figma design using the Figma MCP server. Token values stay as references — no hardcoded hex or px values — and every generated component passes an inline WCAG 2.2 AA contrast check before it is written to disk.

Usage

/figma-component-scaffold <figma-url> [options]

Options:

Flag Values Default Description
--adapter react, razor, astro, vue, sitecore, optimizely, umbraco react Output rendering layer
--tokens file path auto-detect Path to the project's .tokens.json or tokens/ directory
--story flag off Also generate a Storybook story file
--css-strategy modules, tailwind, custom-properties modules CSS output style (React/Astro only)
--output directory path ./src/components/ Where to write generated files

Examples:

/figma-component-scaffold https://figma.com/file/abc123/Design-System?node-id=42-88
/figma-component-scaffold --adapter sitecore --tokens ./src/tokens/tokens.json --story
/figma-component-scaffold https://figma.com/file/abc123?node-id=99-12 --adapter umbraco --output ./Views/Components/

Phase 1 — Read Design Context via Figma MCP

Call the Figma MCP tools in sequence. If the MCP is unavailable, note the limitation and proceed with any design spec or screenshot the user provides.

1.1 Get metadata (high-level node map)

get_metadata(node_url: "<figma-url>")

Extract:

  • Component name → derive the kebab-case slug and PascalCase class name
  • Node type (COMPONENT, FRAME, INSTANCE, COMPONENT_SET for variants)
  • Children structure → layout hierarchy

1.2 Get design context (layout + token references)

get_design_context(node_url: "<figma-url>")

This returns a structured React + Tailwind representation. Extract from it:

  • Layout model: flex/grid, gap, padding, alignment
  • Typography: font family, size, weight, line-height, letter-spacing
  • Color references: distinguish design token names (e.g. color/interactive/primary) from raw hex/RGB values. Raw values without a token name are gaps — flag them.
  • Spacing values: map to the project token scale if available
  • Radius, shadow, border values

1.3 Get variable definitions (token layer)

get_variable_defs(node_url: "<figma-url>")

Extract:

  • All Figma Variables referenced by this component
  • Variable collections (Light, Dark, Brand variants)
  • For each variable: name, resolved value, group path → map to DTCG token path

1.4 Get screenshot (visual reference)

get_screenshot(node_url: "<figma-url>")

Keep as a reference to validate layout fidelity. Check if the screenshot reveals interactive states (hover, focus, active, disabled, error) not captured in the static node tree.


Phase 2 — Analyse Variants and States

If the node is a COMPONENT_SET (multiple variants):

  1. List all variant properties (e.g. Size: sm|md|lg, State: default|hover|focus|disabled|error)
  2. Map each variant to the token values that change between states
  3. Identify which variants map to interactive states — these require ARIA state attributes

Build a variant matrix:

| Variant | Changed tokens | ARIA state |
|---------|----------------|------------|
| State=focus | color/focus/ring | :focus-visible CSS |
| State=disabled | color/interactive/disabled | aria-disabled="true" |
| State=error | color/feedback/error | aria-invalid="true" |

Phase 3 — Token Mapping

Read the project token file. Check for --tokens flag; if not provided, search common locations:

src/tokens/tokens.json
tokens/tokens.json
styles/tokens.json
design-tokens/tokens.json
src/styles/tokens.json

If no token file is found, note the gap and use CSS custom properties with the Figma variable names as property names (e.g. var(--color-interactive-primary)).

For each design value extracted in Phase 1:

Figma Variable DTCG token path CSS custom property Raw fallback
color/interactive/primary color.interactive.primary.$value var(--color-interactive-primary) #0057B8

Flag any raw value with no corresponding token as a token gap — list these in the output summary so the design team can back-fill the Figma Variable.


Phase 4 — Accessibility Pre-Check

Before generating code, validate the token pairs that will be used in this component.

4.1 Contrast Ratios

For every text-on-background pair and icon-on-background pair, compute the contrast ratio using the relative luminance formula (WCAG 1.4.3 / 1.4.11):

L = (R/255, G/255, B/255) → linearise → 0.2126R + 0.7152G + 0.0722B
contrast = (L_lighter + 0.05) / (L_darker + 0.05)

Gates:

  • Body text (< 18pt / < 14pt bold): 4.5:1 minimum
  • Large text (≥ 18pt / ≥ 14pt bold): 3:1 minimum
  • UI components (borders, icons, focus ring): 3:1 minimum (SC 1.4.11)

If a pair fails, output a [CONTRAST FAIL] warning with the calculated ratio and the nearest compliant token alternative if one exists in the token file.

4.2 Interactive Semantics Inventory

Determine the correct ARIA pattern by the component type:

Component type Required semantics
Button <button> or role="button" + tabindex="0" + keyboard handler
Link <a href> — never <div role="link"> without reason
Toggle / Switch role="switch" + aria-checked + keyboard activation
Checkbox <input type="checkbox"> or role="checkbox" + aria-checked
Combobox / Select role="combobox" + aria-expanded + aria-controls
Modal / Dialog role="dialog" + aria-modal="true" + aria-labelledby + focus trap
Accordion role="region" + aria-expanded on trigger + header id relationship
Tab list role="tablist" + role="tab" + aria-selected + arrow-key navigation
Card (linked) Single <a> wrapping or stretch-link pattern — not multiple nested links
Alert role="alert" or role="status" for live region announcements

4.3 Focus Indicator Check

Every interactive component must have a visible :focus-visible style. If the Figma spec shows a focus ring token (e.g. color/focus/ring), use it. If not, apply the project default and flag the missing Figma spec.

Minimum focus indicator (WCAG 2.2 SC 2.4.11): 2 CSS pixels of enclosed perimeter, 3:1 contrast against adjacent background.


Phase 5 — Generate Component Code

Select the output template from reference.md based on --adapter. Apply:

  1. Structure — semantic HTML element hierarchy from the Figma layout
  2. Token references — CSS custom properties or token path imports, no raw values
  3. Variant handling — props/slots for variant properties; map to token and ARIA state changes
  4. ARIA — roles, states, and properties from Phase 4.2
  5. Keyboard — onKeyDown (React) / @keydown (Vue) / addEventListener for Space/Enter on custom interactive elements; arrow keys for composite widgets
  6. Focus — :focus-visible style linked to focus-ring token; tabIndex correct for all states
  7. CSS/styling — follow --css-strategy

5.1 Adapter: React + TypeScript (default)

  • Props interface typed with discriminated union for variants
  • CSS Modules: .module.css with custom property references
  • Or Tailwind: utility classes with cn() helper; token values provided via tailwind.config theme.extend
  • Export as named export from index.ts barrel

5.2 Adapter: Razor / .NET

  • .cshtml partial view with @model <ComponentName>ViewModel
  • ViewModel class with XML doc comments mapping each property to the Figma spec
  • CSS class names follow BEM or the project convention detected from existing files

5.3 Adapter: Astro

  • .astro file with typed Props interface
  • Scoped <style> block using CSS custom properties
  • Client directive guidance: client:visible for interactive components

5.4 Adapter: Vue

  • .vue SFC with <script setup lang="ts">
  • Props defined with defineProps<PropsType>()
  • Scoped styles with CSS custom property references

5.5 Adapter: Sitecore

  • React/TSX + Sitecore JSS ComponentProps interface
  • useSitecoreContext() hook for personalisation context if variants map to personalisation rules
  • Rendering parameter type interface for Sitecore Experience Editor controls
  • SitecoreNextJsPage / sitecorePagePropsFactory integration notes

5.6 Adapter: Optimizely

  • React/TSX + Optimizely Content Cloud BlockComponentProps<TContentType> wrapper
  • Content type mapping: Figma variants → Optimizely property types (string, ContentArea, Url)
  • On-page editing compatibility: avoid position:absolute children that break editor overlays

5.7 Adapter: Umbraco

  • Razor .cshtml + @inject IPublishedContentQuery and typed Umbraco model
  • ModelsBuilder generated type reference or ModelsBuilder-free strongly-typed extension approach
  • Block List / Block Grid editor compatibility: avoid layout assumptions about adjacent blocks

Phase 6 — Storybook Story (--story)

If --story is set, generate a <ComponentName>.stories.tsx (or .stories.ts):

  1. Default story: renders the default variant
  2. One story per named variant (State, Size, etc.)
  3. Accessibility: include parameters.a11y block pointing at the root element
  4. Docs: auto-generate argTypes from the props interface

Phase 7 — Output Summary

Write a summary block at the end of the session:

## Component Scaffold Summary — <ComponentName>

**Figma source:** <url>
**Adapter:** <adapter>
**Files generated:**
  - <path/to/Component.tsx>
  - <path/to/Component.module.css>
  - <path/to/Component.stories.tsx> (if --story)

**Token coverage:**
  - Tokens resolved: N / N
  - Token gaps (no Figma Variable): <list raw values>

**Accessibility pre-check:**
  - Contrast: PASS / FAIL (list failing pairs)
  - ARIA pattern: <pattern used>
  - Keyboard model: <Enter/Space|arrow-keys|none>
  - Focus indicator: PASS / FLAGGED

**Next steps:**
  - Run /component-a11y-gate on the generated files for a full static review
  - Back-fill missing Figma Variables for flagged token gaps
  - Run /design-system-sync if token file is out of date with Figma Variables

Reference files

  • reference.md — Component templates per adapter (React, Razor, Astro, Vue, Sitecore, Optimizely, Umbraco)
  • examples.md — Worked examples: Card, Button, Form Field, Navigation, Modal, Tab List
  • templates.md — Storybook story templates, ViewModel class templates, Sitecore/Optimizely/Umbraco model stubs
Technical details
Plugin
design-to-code-builder
Author
Dakota Smith
Skill name
figma-component-scaffold
Maturity
experimental
Security review
No security review
Owners
  • engineering
  • design
Argument hint
<figma-url-or-selection> [--adapter react|razor|astro|vue|sitecore|optimizely|umbraco] [--tokens <path-to-tokens.json>] [--story]
Allowed tools
  • Read
  • Write
  • Edit
  • Glob
  • Grep
  • mcp__figma-dev-mode-mcp-server__get_design_context
  • mcp__figma-dev-mode-mcp-server__get_variable_defs
  • mcp__figma-dev-mode-mcp-server__get_metadata
  • mcp__figma-dev-mode-mcp-server__get_screenshot
  • Bash(node *)
  • Bash(npx prettier *)
  • Bash(npx tsc --noEmit *)
Source
plugins/design-to-code-builder/skills/figma-component-scaffold/SKILL.md

Edit this skill on GitHub — opens GitHub's web editor. No git knowledge needed.