figma-console-mcp 1.21.1 β†’ 1.22.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -8,7 +8,7 @@
8
8
 
9
9
  > **Your design system as an API.** Model Context Protocol server that bridges design and developmentβ€”giving AI assistants complete access to Figma for **extraction**, **creation**, and **debugging**.
10
10
 
11
- > **πŸ†• High-Fidelity Design-to-Code:** Deep component trees (depth 4), resolved design tokens, interaction state machines with CSS mappings, and codebase-aware component scanning. AI gets everything a senior engineer needs β€” tokens, sizing, states, annotations, and a cross-reference of what already exists in your codebase. [See what's new β†’](docs/figma-mcp-vs-figma-console-mcp.md)
11
+ > **πŸ†• Comprehensive Accessibility Scanning (v1.22.0):** Full-spectrum WCAG coverage across design and code β€” 13 design-side lint rules, component accessibility scorecards with color-blind simulation, code-side scanning via axe-core (104 rules), and design-to-code accessibility parity checking. No rule database to maintain. [See what's new β†’](docs/figma-mcp-vs-figma-console-mcp.md)
12
12
 
13
13
  ## What is this?
14
14
 
@@ -21,6 +21,7 @@ Figma Console MCP connects AI assistants (like Claude) to Figma, enabling:
21
21
  - **πŸ”§ Variable management** - Create, update, rename, and delete design tokens
22
22
  - **⚑ Real-time monitoring** - Watch logs as plugins execute
23
23
  - **πŸ“Œ FigJam boards** - Create stickies, flowcharts, tables, and code blocks on collaborative boards
24
+ - **β™Ώ Accessibility scanning** - 13 WCAG design checks, component scorecards, axe-core code scanning, design-to-code parity
24
25
  - **☁️ Cloud Write Relay** - Web AI clients (Claude.ai, v0, Replit) can design in Figma via cloud pairing
25
26
  - **πŸ”„ Four ways to connect** - Remote SSE, Cloud Mode, NPX, or Local Git
26
27
 
@@ -51,9 +52,9 @@ Figma Console MCP connects AI assistants (like Claude) to Figma, enabling:
51
52
  | Real-time monitoring (console, selection) | βœ… | ❌ | ❌ |
52
53
  | Desktop Bridge plugin | βœ… | βœ… | ❌ |
53
54
  | Requires Node.js | Yes | **No** | No |
54
- | **Total tools available** | **92+** | **43** | **22** |
55
+ | **Total tools available** | **94+** | **43** | **22** |
55
56
 
56
- > **Bottom line:** Remote SSE is **read-only** with ~38% of the tools. **Cloud Mode** unlocks write access from web AI clients without Node.js. NPX/Local Git gives the full 92+ tools with real-time monitoring.
57
+ > **Bottom line:** Remote SSE is **read-only** with ~38% of the tools. **Cloud Mode** unlocks write access from web AI clients without Node.js. NPX/Local Git gives the full 94+ tools with real-time monitoring.
57
58
 
58
59
  ---
59
60
 
@@ -61,7 +62,7 @@ Figma Console MCP connects AI assistants (like Claude) to Figma, enabling:
61
62
 
62
63
  **Best for:** Designers who want full AI-assisted design capabilities.
63
64
 
64
- **What you get:** All 92+ tools including design creation, variable management, and component instantiation.
65
+ **What you get:** All 94+ tools including design creation, variable management, and component instantiation.
65
66
 
66
67
  #### Prerequisites
67
68
 
@@ -156,7 +157,7 @@ Create a simple frame with a blue background
156
157
 
157
158
  **Best for:** Developers who want to modify source code or contribute to the project.
158
159
 
159
- **What you get:** Same 92+ tools as NPX, plus full source code access.
160
+ **What you get:** Same 94+ tools as NPX, plus full source code access.
160
161
 
161
162
  #### Quick Setup
162
163
 
@@ -245,7 +246,7 @@ Ready for design creation? Follow the [NPX Setup](#-npx-setup-recommended) guide
245
246
 
246
247
  **Best for:** Using Claude.ai, v0, Replit, or Lovable to create and modify Figma designs β€” no Node.js required.
247
248
 
248
- **What you get:** 82 tools including full write access β€” design creation, variable management, component instantiation, and all REST API tools. Only real-time monitoring (console logs, selection tracking, document changes) requires Local Mode.
249
+ **What you get:** 83 tools including full write access β€” design creation, variable management, component instantiation, and all REST API tools. Only real-time monitoring (console logs, selection tracking, document changes) requires Local Mode.
249
250
 
250
251
  #### Prerequisites
251
252
 
@@ -302,7 +303,7 @@ AI Client β†’ Cloud MCP Server β†’ Durable Object Relay β†’ Desktop Bridge Plugi
302
303
  | Feature | NPX (Recommended) | Cloud Mode | Local Git | Remote SSE |
303
304
  |---------|-------------------|------------|-----------|------------|
304
305
  | **Setup time** | ~10 minutes | ~5 minutes | ~15 minutes | ~2 minutes |
305
- | **Total tools** | **92+** | **43** | **92+** | **22** (read-only) |
306
+ | **Total tools** | **94+** | **43** | **94+** | **22** (read-only) |
306
307
  | **Design creation** | βœ… | βœ… | βœ… | ❌ |
307
308
  | **Variable management** | βœ… | βœ… | βœ… | ❌ |
308
309
  | **Component instantiation** | βœ… | βœ… | βœ… | ❌ |
@@ -317,7 +318,7 @@ AI Client β†’ Cloud MCP Server β†’ Durable Object Relay β†’ Desktop Bridge Plugi
317
318
  | **Automatic updates** | βœ… (`@latest`) | βœ… | Manual (`git pull`) | βœ… |
318
319
  | **Source code access** | ❌ | ❌ | βœ… | ❌ |
319
320
 
320
- > **Key insight:** Remote SSE is read-only. Cloud Mode adds write access for web AI clients without Node.js. NPX/Local Git give the full 92+ tools.
321
+ > **Key insight:** Remote SSE is read-only. Cloud Mode adds write access for web AI clients without Node.js. NPX/Local Git give the full 94+ tools.
321
322
 
322
323
  **πŸ“– [Complete Feature Comparison](docs/mode-comparison.md)**
323
324
 
@@ -651,7 +652,7 @@ The **Figma Desktop Bridge** plugin is the recommended way to connect Figma to t
651
652
  - The MCP server communicates via **WebSocket** through the Desktop Bridge plugin
652
653
  - The server tries port 9223 first, then automatically falls back through ports 9224–9232 if needed
653
654
  - The plugin scans all ports in the range and connects to every active server it finds
654
- - All 92+ tools work through the WebSocket transport
655
+ - All 94+ tools work through the WebSocket transport
655
656
 
656
657
  **Multiple files:** The WebSocket server supports multiple simultaneous plugin connections β€” one per open Figma file. Each connection is tracked by file key with independent state (selection, document changes, console logs).
657
658
 
@@ -788,7 +789,7 @@ The architecture supports adding new apps with minimal boilerplate β€” each app
788
789
 
789
790
  ## πŸ›€οΈ Roadmap
790
791
 
791
- **Current Status:** v1.17.0 (Stable) - Production-ready with FigJam + Slides support, Cloud Write Relay, Design System Kit, WebSocket-only connectivity, smart multi-file tracking, 92+ tools, Comments API, and MCP Apps
792
+ **Current Status:** v1.17.0 (Stable) - Production-ready with FigJam + Slides support, Cloud Write Relay, Design System Kit, WebSocket-only connectivity, smart multi-file tracking, 94+ tools, Comments API, and MCP Apps
792
793
 
793
794
  **Recent Releases:**
794
795
  - [x] **v1.17.0** - Figma Slides Support: 15 new tools for managing presentations β€” slides, transitions, content, reordering, and navigation. Inspired by Toni Haidamous (PR #11).
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Code-side accessibility scanning via axe-core + JSDOM.
3
+ *
4
+ * Delegates all rule logic to axe-core (Deque) β€” the MCP never owns
5
+ * a rule database. JSDOM provides a lightweight DOM for structural checks
6
+ * (~50 rules: ARIA, semantics, alt text, form labels, headings, landmarks).
7
+ *
8
+ * Visual rules (color contrast, focus-visible) are NOT available via JSDOM β€”
9
+ * those are handled by the design-side figma_lint_design tool.
10
+ */
11
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
12
+ /**
13
+ * Extract a CodeSpec.accessibility object from HTML + axe-core results.
14
+ * This bridges Phase 3 (code scanning) β†’ Phase 4 (parity comparison).
15
+ *
16
+ * Parses the HTML to extract semantic element, ARIA attributes, and states.
17
+ * Uses axe-core results to infer what the code supports.
18
+ */
19
+ export declare function axeResultsToCodeSpec(html: string, axeResults: any): Record<string, any>;
20
+ export declare function registerAccessibilityTools(server: McpServer): void;
21
+ //# sourceMappingURL=accessibility-tools.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"accessibility-tools.d.ts","sourceRoot":"","sources":["../../src/core/accessibility-tools.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AA6FpE;;;;;;GAMG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,EAAE,UAAU,EAAE,GAAG,GAAG,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAoGvF;AA+DD,wBAAgB,0BAA0B,CACzC,MAAM,EAAE,SAAS,GACf,IAAI,CAyEN"}
@@ -0,0 +1,307 @@
1
+ /**
2
+ * Code-side accessibility scanning via axe-core + JSDOM.
3
+ *
4
+ * Delegates all rule logic to axe-core (Deque) β€” the MCP never owns
5
+ * a rule database. JSDOM provides a lightweight DOM for structural checks
6
+ * (~50 rules: ARIA, semantics, alt text, form labels, headings, landmarks).
7
+ *
8
+ * Visual rules (color contrast, focus-visible) are NOT available via JSDOM β€”
9
+ * those are handled by the design-side figma_lint_design tool.
10
+ */
11
+ import { z } from "zod";
12
+ import { logger } from "./logger.js";
13
+ // Lazy-load axe-core and jsdom to keep them optional
14
+ let axeCore = null;
15
+ let JSDOM = null;
16
+ let depsLoaded = false;
17
+ let depsError = null;
18
+ async function loadDeps() {
19
+ if (depsLoaded)
20
+ return;
21
+ try {
22
+ axeCore = await import("axe-core");
23
+ // axe-core's default export structure
24
+ if (axeCore.default)
25
+ axeCore = axeCore.default;
26
+ const jsdomModule = await import("jsdom");
27
+ JSDOM = jsdomModule.JSDOM;
28
+ depsLoaded = true;
29
+ }
30
+ catch (e) {
31
+ depsError = `axe-core or jsdom not installed. Run: npm install axe-core jsdom\n${e.message}`;
32
+ throw new Error(depsError);
33
+ }
34
+ }
35
+ /**
36
+ * Run axe-core against an HTML string using JSDOM.
37
+ *
38
+ * JSDOM limitations: no computed styles, no layout, no visual rendering.
39
+ * This means ~50-60 structural rules work, but visual rules
40
+ * (color-contrast, focus-visible, etc.) will report as "incomplete".
41
+ */
42
+ async function scanHtmlWithAxe(html, options = {}) {
43
+ await loadDeps();
44
+ // Wrap HTML fragment in a full document if needed
45
+ const fullHtml = html.includes("<html") || html.includes("<!DOCTYPE")
46
+ ? html
47
+ : `<!DOCTYPE html><html lang="en"><head><title>Scan</title></head><body>${html}</body></html>`;
48
+ const dom = new JSDOM(fullHtml, {
49
+ runScripts: "dangerously",
50
+ pretendToBeVisual: true,
51
+ url: "http://localhost",
52
+ });
53
+ const { document, window } = dom.window;
54
+ // Inject axe-core into the JSDOM window
55
+ const axeSource = axeCore.source;
56
+ const scriptEl = document.createElement("script");
57
+ scriptEl.textContent = axeSource;
58
+ document.head.appendChild(scriptEl);
59
+ // Configure axe run options
60
+ const runOptions = {};
61
+ if (options.tags && options.tags.length > 0) {
62
+ runOptions.runOnly = { type: "tag", values: options.tags };
63
+ }
64
+ // Disable rules that require visual rendering (always fail/incomplete in JSDOM)
65
+ if (options.disableVisualRules !== false) {
66
+ runOptions.rules = {
67
+ "color-contrast": { enabled: false },
68
+ "color-contrast-enhanced": { enabled: false },
69
+ "link-in-text-block": { enabled: false },
70
+ };
71
+ }
72
+ // Determine scan context
73
+ const context = options.context || document;
74
+ try {
75
+ const results = await window.axe.run(context, runOptions);
76
+ // Clean up
77
+ dom.window.close();
78
+ return results;
79
+ }
80
+ catch (err) {
81
+ dom.window.close();
82
+ throw new Error(`axe-core scan failed: ${err.message}`);
83
+ }
84
+ }
85
+ /**
86
+ * Extract a CodeSpec.accessibility object from HTML + axe-core results.
87
+ * This bridges Phase 3 (code scanning) β†’ Phase 4 (parity comparison).
88
+ *
89
+ * Parses the HTML to extract semantic element, ARIA attributes, and states.
90
+ * Uses axe-core results to infer what the code supports.
91
+ */
92
+ export function axeResultsToCodeSpec(html, axeResults) {
93
+ const spec = {};
94
+ // Parse HTML to extract attributes (lightweight regex-based, no DOM needed)
95
+ const htmlLower = html.toLowerCase();
96
+ // Semantic element: find the root/first meaningful element
97
+ const rootElementMatch = html.match(/<(button|a|input|select|textarea|details|dialog|nav|main|form|label|fieldset)\b/i);
98
+ if (rootElementMatch) {
99
+ spec.semanticElement = rootElementMatch[1].toLowerCase();
100
+ }
101
+ else {
102
+ const firstElementMatch = html.match(/<(\w+)[\s>]/);
103
+ if (firstElementMatch && !["div", "span", "html", "head", "body", "script", "style", "!doctype"].includes(firstElementMatch[1].toLowerCase())) {
104
+ spec.semanticElement = firstElementMatch[1].toLowerCase();
105
+ }
106
+ else {
107
+ spec.semanticElement = "div";
108
+ }
109
+ }
110
+ // ARIA role
111
+ const roleMatch = html.match(/role=["']([^"']+)["']/i);
112
+ if (roleMatch) {
113
+ spec.role = roleMatch[1];
114
+ }
115
+ // ARIA label
116
+ const ariaLabelMatch = html.match(/aria-label=["']([^"']+)["']/i);
117
+ if (ariaLabelMatch) {
118
+ spec.ariaLabel = ariaLabelMatch[1];
119
+ }
120
+ // Focus visible: check for :focus-visible or :focus in inline styles/class names,
121
+ // or infer from element type (native interactive elements have default focus)
122
+ const nativeFocusElements = ["button", "a", "input", "select", "textarea"];
123
+ const hasFocusCSS = /focus-visible|:focus\b|outline.*focus|ring.*focus|focus.*ring/i.test(html);
124
+ spec.focusVisible = hasFocusCSS || nativeFocusElements.includes(spec.semanticElement || "");
125
+ // Disabled support: only assert true when we find positive evidence.
126
+ // Absence of disabled/aria-disabled in a single HTML snapshot does NOT mean
127
+ // the component lacks disabled support β€” it may be in a non-disabled state.
128
+ if (/\bdisabled\b|aria-disabled/i.test(htmlLower)) {
129
+ spec.supportsDisabled = true;
130
+ }
131
+ // (leave undefined when not found β€” absence β‰  lack of support)
132
+ // Error support: same principle β€” only assert true on positive evidence.
133
+ // A default-state HTML snippet won't have aria-invalid; that doesn't mean
134
+ // the component can't enter an error state.
135
+ if (/aria-invalid|aria-errormessage|aria-describedby.*error/i.test(htmlLower)) {
136
+ spec.supportsError = true;
137
+ }
138
+ // (leave undefined when not found β€” scan a different state to confirm)
139
+ // Required: check for required or aria-required attributes
140
+ if (/aria-required=["']true["']|required(?!=)/i.test(html)) {
141
+ spec.ariaRequired = true;
142
+ }
143
+ else if (/aria-required=["']false["']/i.test(html)) {
144
+ spec.ariaRequired = false;
145
+ }
146
+ // Keyboard interactions: infer from element type
147
+ const keyboardInteractions = [];
148
+ if (spec.semanticElement === "button" || spec.role === "button") {
149
+ keyboardInteractions.push("Enter", "Space");
150
+ }
151
+ else if (spec.semanticElement === "a" || spec.role === "link") {
152
+ keyboardInteractions.push("Enter");
153
+ }
154
+ else if (spec.semanticElement === "input" || spec.semanticElement === "textarea") {
155
+ keyboardInteractions.push("Tab (focus)", "Type (input)");
156
+ }
157
+ else if (spec.semanticElement === "select" || spec.role === "listbox") {
158
+ keyboardInteractions.push("Arrow keys", "Enter", "Space");
159
+ }
160
+ else if (spec.role === "checkbox" || spec.role === "switch") {
161
+ keyboardInteractions.push("Space");
162
+ }
163
+ else if (spec.role === "tab") {
164
+ keyboardInteractions.push("Arrow keys");
165
+ }
166
+ // Check HTML for custom keyboard handlers
167
+ if (/onkeydown|onkeyup|onkeypress|@keydown|@keyup|v-on:keydown/i.test(html)) {
168
+ if (!keyboardInteractions.includes("Custom key handler")) {
169
+ keyboardInteractions.push("Custom key handler");
170
+ }
171
+ }
172
+ if (keyboardInteractions.length > 0) {
173
+ spec.keyboardInteractions = keyboardInteractions;
174
+ }
175
+ // Use axe-core results to refine: if certain violations exist, it tells us what's missing
176
+ if (axeResults?.violations) {
177
+ for (const v of axeResults.violations) {
178
+ // If button-name violation exists, the button has no accessible name
179
+ if (v.id === "button-name") {
180
+ spec.ariaLabel = undefined; // Explicitly missing
181
+ }
182
+ // If label violation exists, input lacks a label
183
+ if (v.id === "label") {
184
+ spec.ariaLabel = undefined;
185
+ }
186
+ }
187
+ }
188
+ return spec;
189
+ }
190
+ /**
191
+ * Format axe-core results into our standard lint-like output structure.
192
+ */
193
+ function formatAxeResults(axeResults) {
194
+ const categories = [];
195
+ const severityMap = {
196
+ critical: "critical",
197
+ serious: "critical",
198
+ moderate: "warning",
199
+ minor: "info",
200
+ };
201
+ // Group violations
202
+ for (const violation of axeResults.violations || []) {
203
+ const severity = severityMap[violation.impact] || "warning";
204
+ const nodes = violation.nodes.map((node) => ({
205
+ html: node.html?.substring(0, 200),
206
+ target: node.target,
207
+ failureSummary: node.failureSummary?.substring(0, 300),
208
+ }));
209
+ categories.push({
210
+ rule: violation.id,
211
+ severity,
212
+ count: violation.nodes.length,
213
+ description: violation.help,
214
+ wcagTags: violation.tags.filter((t) => t.startsWith("wcag") || t.startsWith("best-practice")),
215
+ helpUrl: violation.helpUrl,
216
+ nodes: nodes.slice(0, 10), // Cap at 10 per rule
217
+ });
218
+ }
219
+ // Sort: critical first, then by count
220
+ categories.sort((a, b) => {
221
+ const sevOrder = { critical: 0, warning: 1, info: 2 };
222
+ if (sevOrder[a.severity] !== sevOrder[b.severity]) {
223
+ return sevOrder[a.severity] - sevOrder[b.severity];
224
+ }
225
+ return b.count - a.count;
226
+ });
227
+ // Summary
228
+ const summary = { critical: 0, warning: 0, info: 0, total: 0 };
229
+ for (const cat of categories) {
230
+ summary[cat.severity] += cat.count;
231
+ summary.total += cat.count;
232
+ }
233
+ return {
234
+ engine: "axe-core",
235
+ version: axeResults.testEngine?.version || "unknown",
236
+ mode: "jsdom-structural",
237
+ note: "JSDOM mode: structural/semantic checks only. Visual rules (color contrast, focus visibility) are disabled β€” use figma_lint_design for visual accessibility checks.",
238
+ categories,
239
+ summary,
240
+ passes: axeResults.passes?.length || 0,
241
+ incomplete: axeResults.incomplete?.length || 0,
242
+ inapplicable: axeResults.inapplicable?.length || 0,
243
+ };
244
+ }
245
+ export function registerAccessibilityTools(server) {
246
+ server.tool("figma_scan_code_accessibility", "Scan HTML code for accessibility violations using axe-core (Deque). " +
247
+ "Runs structural/semantic checks via JSDOM: ARIA attributes, roles, labels, alt text, " +
248
+ "form labels, heading order, landmarks, semantic HTML, tabindex, duplicate IDs, lang attribute, and ~50 more rules. " +
249
+ "Visual checks (color contrast, focus visibility) are disabled in this mode β€” use figma_lint_design for visual a11y on the design side. " +
250
+ "Together, these two tools provide full-spectrum accessibility coverage across design and code. " +
251
+ "Pass component HTML directly or use with figma_check_design_parity for design-to-code a11y comparison. " +
252
+ "No Figma connection required β€” this is a standalone code analysis tool.", {
253
+ html: z.string().describe("HTML string to scan. Can be a full document or a component fragment (will be wrapped in a valid document)."),
254
+ tags: z.array(z.string()).optional().describe("WCAG tag filter. Examples: ['wcag2a'], ['wcag2aa'], ['wcag21aa'], ['wcag22aa'], ['best-practice']. " +
255
+ "Defaults to all structural rules if omitted."),
256
+ context: z.string().optional().describe("CSS selector to scope the scan to a specific element (e.g., '#my-component', '.card'). Scans entire document if omitted."),
257
+ includePassingRules: z.boolean().optional().describe("If true, includes count of passing and incomplete rules in the response (default: false)."),
258
+ mapToCodeSpec: z.boolean().optional().describe("If true, includes a codeSpec.accessibility object auto-extracted from the HTML + scan results. " +
259
+ "Pass this directly into figma_check_design_parity's codeSpec.accessibility field for automated design-to-code a11y parity checking."),
260
+ }, async ({ html, tags, context, includePassingRules, mapToCodeSpec }) => {
261
+ try {
262
+ const axeResults = await scanHtmlWithAxe(html, {
263
+ tags: tags || undefined,
264
+ context: context || undefined,
265
+ });
266
+ const formatted = formatAxeResults(axeResults);
267
+ // Optionally strip pass/incomplete counts to save tokens
268
+ if (!includePassingRules) {
269
+ delete formatted.passes;
270
+ delete formatted.incomplete;
271
+ delete formatted.inapplicable;
272
+ }
273
+ // Auto-generate CodeSpec.accessibility from HTML + results
274
+ if (mapToCodeSpec) {
275
+ formatted.codeSpecAccessibility = axeResultsToCodeSpec(html, axeResults);
276
+ formatted.codeSpecAccessibility._usage = "Pass this object as codeSpec.accessibility in figma_check_design_parity for automated a11y parity checking.";
277
+ }
278
+ return {
279
+ content: [
280
+ {
281
+ type: "text",
282
+ text: JSON.stringify(formatted, null, 2),
283
+ },
284
+ ],
285
+ };
286
+ }
287
+ catch (error) {
288
+ const isDepsError = error.message?.includes("not installed");
289
+ logger.error({ error }, "Failed to scan code accessibility");
290
+ return {
291
+ content: [
292
+ {
293
+ type: "text",
294
+ text: JSON.stringify({
295
+ error: error.message,
296
+ hint: isDepsError
297
+ ? "Install dependencies: npm install axe-core jsdom"
298
+ : "Check that the HTML is valid. For visual accessibility checks, use figma_lint_design instead.",
299
+ }),
300
+ },
301
+ ],
302
+ isError: true,
303
+ };
304
+ }
305
+ });
306
+ }
307
+ //# sourceMappingURL=accessibility-tools.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"accessibility-tools.js","sourceRoot":"","sources":["../../src/core/accessibility-tools.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"design-code-tools.d.ts","sourceRoot":"","sources":["../../src/core/design-code-tools.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"design-code-tools.d.ts","sourceRoot":"","sources":["../../src/core/design-code-tools.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAEzE,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAK/C,OAAO,KAAK,EAUX,uBAAuB,EACvB,MAAM,wBAAwB,CAAC;AAShC,oDAAoD;AACpD,wBAAgB,cAAc,CAAC,KAAK,EAAE;IAAE,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,MAAM,CAU7F;AAED,4FAA4F;AAC5F,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAWpD;AAED,8CAA8C;AAC9C,wBAAgB,YAAY,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,SAAS,GAAE,MAAU,GAAG,OAAO,CAEjF;AAED,qDAAqD;AACrD,wBAAgB,oBAAoB,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAEzG;AAiED,oEAAoE;AACpE,wBAAgB,sBAAsB,CAAC,QAAQ,EAAE,MAAM,GAAG,KAAK,CAAC;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC,CAqBpG;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAUxD;AAMD,sEAAsE;AACtE,UAAU,iBAAiB;IAC1B,qCAAqC;IACrC,QAAQ,EAAE,MAAM,CAAC;IACjB,kCAAkC;IAClC,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,sCAAsC;IACtC,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,uEAAuE;IACvE,iBAAiB,EAAE,KAAK,CAAC;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC,CAAC;IAC/D,0BAA0B;IAC1B,kBAAkB,EAAE,MAAM,EAAE,CAAC;IAC7B,yCAAyC;IACzC,eAAe,EAAE,MAAM,EAAE,CAAC;CAC1B;AAED;;;GAGG;AACH,wBAAgB,yBAAyB,CAAC,WAAW,EAAE,MAAM,GAAG,iBAAiB,CA0KhF;AAMD,mDAAmD;AACnD,UAAU,gBAAgB;IACzB,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,KAAK,CAAC;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAC;QAAC,UAAU,CAAC,EAAE,MAAM,CAAC;QAAC,YAAY,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC5F,OAAO,EAAE,KAAK,CAAC;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAC;QAAC,UAAU,CAAC,EAAE,MAAM,CAAC;QAAC,YAAY,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC9F,UAAU,EAAE,KAAK,CAAC;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAC;QAAC,UAAU,CAAC,EAAE,MAAM,CAAC;QAAC,YAAY,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACjG,KAAK,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CAC7C;AAED,uCAAuC;AACvC,UAAU,aAAa;IACtB,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,cAAc,EAAE,MAAM,CAAC;IACvB,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,aAAa,EAAE,MAAM,CAAC;IACtB,gBAAgB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC1C;AAED;;;GAGG;AACH,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,GAAG,EAAE,UAAU,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,gBAAgB,EAAE,CAqBpG;AAoED;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,GAAG,EAAE,KAAK,GAAE,MAAU,EAAE,QAAQ,GAAE,MAAU,GAAG,aAAa,EAAE,CAiCzG;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,GAAG,EAAE,KAAK,GAAE,MAAU,EAAE,QAAQ,GAAE,MAAU,GAAG,MAAM,CAqB3F;AAmHD;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,GAAG,GAAG,GAAG,CAKhD;AAED,oGAAoG;AACpG,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAEnD;AAED,uDAAuD;AACvD,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAE1D;AA8uDD,gFAAgF;AAChF,wBAAgB,kBAAkB,CACjC,QAAQ,EAAE,MAAM,EAChB,aAAa,EAAE,MAAM,EACrB,QAAQ,EAAE,MAAM,EAChB,UAAU,CAAC,EAAE,MAAM,GACjB,uBAAuB,CAazB;AAqJD,wBAAgB,uBAAuB,CACtC,MAAM,EAAE,SAAS,EACjB,WAAW,EAAE,MAAM,OAAO,CAAC,QAAQ,CAAC,EACpC,aAAa,EAAE,MAAM,MAAM,GAAG,IAAI,EAClC,cAAc,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE;IAAE,IAAI,EAAE,GAAG,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,CAAC,EAC9D,OAAO,CAAC,EAAE;IAAE,YAAY,CAAC,EAAE,OAAO,CAAA;CAAE,EACpC,mBAAmB,CAAC,EAAE,MAAM,OAAO,CAAC,GAAG,CAAC,GACtC,IAAI,CAijBN"}
@@ -990,7 +990,9 @@ function compareAccessibility(node, codeSpec, discrepancies) {
990
990
  return;
991
991
  // Check description/annotations for accessibility hints
992
992
  const description = node.descriptionMarkdown || node.description || "";
993
- const hasAriaAnnotation = description.toLowerCase().includes("aria") || description.toLowerCase().includes("accessibility");
993
+ const descLower = description.toLowerCase();
994
+ const hasAriaAnnotation = descLower.includes("aria") || descLower.includes("accessibility");
995
+ // ---- 1. ARIA Role Parity ----
994
996
  if (ca.role && !hasAriaAnnotation) {
995
997
  discrepancies.push({
996
998
  category: "accessibility",
@@ -1002,6 +1004,35 @@ function compareAccessibility(node, codeSpec, discrepancies) {
1002
1004
  suggestion: "Add accessibility annotations in Figma description",
1003
1005
  });
1004
1006
  }
1007
+ // ---- 2. Semantic Element vs Component Name ----
1008
+ if (ca.semanticElement) {
1009
+ const nodeName = (node.name || "").toLowerCase();
1010
+ const element = ca.semanticElement.toLowerCase();
1011
+ // Check if interactive component uses correct semantic element
1012
+ const interactivePattern = /button|link|input|checkbox|radio|switch|toggle|tab|select/i;
1013
+ if (interactivePattern.test(nodeName)) {
1014
+ const elementMatchesDesign = (nodeName.includes("button") && (element === "button" || ca.role === "button")) ||
1015
+ (nodeName.includes("link") && (element === "a" || ca.role === "link")) ||
1016
+ (nodeName.includes("input") && (element === "input" || element === "textarea")) ||
1017
+ (nodeName.includes("checkbox") && (element === "input" || ca.role === "checkbox")) ||
1018
+ (nodeName.includes("radio") && (element === "input" || ca.role === "radio")) ||
1019
+ (nodeName.includes("switch") && (ca.role === "switch" || element === "input")) ||
1020
+ (nodeName.includes("select") && (element === "select" || ca.role === "listbox")) ||
1021
+ (nodeName.includes("tab") && (ca.role === "tab" || element === "button"));
1022
+ if (!elementMatchesDesign) {
1023
+ discrepancies.push({
1024
+ category: "accessibility",
1025
+ property: "semanticElement",
1026
+ severity: "major",
1027
+ designValue: nodeName,
1028
+ codeValue: `<${element}>${ca.role ? ` role="${ca.role}"` : ""}`,
1029
+ message: `Design component "${node.name}" may not match code element <${element}>`,
1030
+ suggestion: `Verify that <${element}> is the correct semantic element for a component named "${node.name}". Use native HTML elements over ARIA roles where possible.`,
1031
+ });
1032
+ }
1033
+ }
1034
+ }
1035
+ // ---- 3. Contrast Ratio ----
1005
1036
  if (ca.contrastRatio !== undefined && ca.contrastRatio < 4.5) {
1006
1037
  discrepancies.push({
1007
1038
  category: "accessibility",
@@ -1013,6 +1044,129 @@ function compareAccessibility(node, codeSpec, discrepancies) {
1013
1044
  suggestion: "Increase contrast ratio to at least 4.5:1",
1014
1045
  });
1015
1046
  }
1047
+ // ---- 4. Focus Indicator Parity ----
1048
+ // Check if design has a focus variant but code doesn't implement focus-visible
1049
+ const variants = node.children || [];
1050
+ const hasFocusVariant = variants.some((v) => /focus|focused/i.test(v.name || ""));
1051
+ if (hasFocusVariant && ca.focusVisible === false) {
1052
+ discrepancies.push({
1053
+ category: "accessibility",
1054
+ property: "focusVisible",
1055
+ severity: "critical",
1056
+ designValue: "focus variant exists",
1057
+ codeValue: "focusVisible: false",
1058
+ message: "Design has a focus variant but code does not implement :focus-visible styles",
1059
+ suggestion: "Add :focus-visible CSS with a visible focus ring matching the design's focus variant (WCAG 2.4.7)",
1060
+ });
1061
+ }
1062
+ else if (!hasFocusVariant && ca.focusVisible === true) {
1063
+ discrepancies.push({
1064
+ category: "accessibility",
1065
+ property: "focusVisible",
1066
+ severity: "minor",
1067
+ designValue: "no focus variant",
1068
+ codeValue: "focusVisible: true",
1069
+ message: "Code implements :focus-visible but design has no focus variant to specify the visual treatment",
1070
+ suggestion: "Add a focus/focused variant in Figma to document the intended focus indicator design",
1071
+ });
1072
+ }
1073
+ // ---- 5. Disabled State Parity ----
1074
+ const hasDisabledVariant = variants.some((v) => /disabled|inactive/i.test(v.name || ""));
1075
+ if (hasDisabledVariant && ca.supportsDisabled === false) {
1076
+ discrepancies.push({
1077
+ category: "accessibility",
1078
+ property: "disabled",
1079
+ severity: "major",
1080
+ designValue: "disabled variant exists",
1081
+ codeValue: "supportsDisabled: false",
1082
+ message: "Design has a disabled variant but code does not support disabled/aria-disabled state",
1083
+ suggestion: "Implement disabled or aria-disabled attribute support in the component",
1084
+ });
1085
+ }
1086
+ else if (!hasDisabledVariant && ca.supportsDisabled === true) {
1087
+ discrepancies.push({
1088
+ category: "accessibility",
1089
+ property: "disabled",
1090
+ severity: "minor",
1091
+ designValue: "no disabled variant",
1092
+ codeValue: "supportsDisabled: true",
1093
+ message: "Code supports disabled state but design has no disabled variant",
1094
+ suggestion: "Add a disabled variant in Figma showing the visual treatment for disabled state",
1095
+ });
1096
+ }
1097
+ // ---- 6. Error State Parity ----
1098
+ const hasErrorVariant = variants.some((v) => /error|invalid|danger/i.test(v.name || ""));
1099
+ if (hasErrorVariant && ca.supportsError === false) {
1100
+ discrepancies.push({
1101
+ category: "accessibility",
1102
+ property: "errorState",
1103
+ severity: "major",
1104
+ designValue: "error variant exists",
1105
+ codeValue: "supportsError: false",
1106
+ message: "Design has an error variant but code does not support aria-invalid or error messaging",
1107
+ suggestion: "Implement aria-invalid attribute and associated error message (aria-describedby) in the component",
1108
+ });
1109
+ }
1110
+ // ---- 7. Required Field Parity ----
1111
+ if (ca.ariaRequired !== undefined) {
1112
+ const hasRequiredVariant = variants.some((v) => /required/i.test(v.name || ""));
1113
+ const hasRequiredInDescription = descLower.includes("required");
1114
+ if (ca.ariaRequired && !hasRequiredVariant && !hasRequiredInDescription) {
1115
+ discrepancies.push({
1116
+ category: "accessibility",
1117
+ property: "required",
1118
+ severity: "minor",
1119
+ designValue: "no required indicator",
1120
+ codeValue: "ariaRequired: true",
1121
+ message: "Code marks field as required but design has no visual required indicator",
1122
+ suggestion: "Add a required indicator (asterisk, label text) in the design and/or a required variant",
1123
+ });
1124
+ }
1125
+ }
1126
+ // ---- 8. Target Size Parity ----
1127
+ if (ca.renderedSize) {
1128
+ const [codeWidth, codeHeight] = ca.renderedSize;
1129
+ const designWidth = node.absoluteBoundingBox?.width || node.size?.x;
1130
+ const designHeight = node.absoluteBoundingBox?.height || node.size?.y;
1131
+ if (designWidth && designHeight) {
1132
+ // Check if code size is significantly smaller than design (>20% reduction)
1133
+ if (codeWidth < designWidth * 0.8 || codeHeight < designHeight * 0.8) {
1134
+ discrepancies.push({
1135
+ category: "accessibility",
1136
+ property: "targetSize",
1137
+ severity: "major",
1138
+ designValue: `${Math.round(designWidth)}x${Math.round(designHeight)}`,
1139
+ codeValue: `${codeWidth}x${codeHeight}`,
1140
+ message: `Code renders significantly smaller (${codeWidth}x${codeHeight}px) than design (${Math.round(designWidth)}x${Math.round(designHeight)}px)`,
1141
+ suggestion: "Ensure rendered component meets the design's touch target size. Check CSS min-width/min-height.",
1142
+ });
1143
+ }
1144
+ // Check WCAG 2.5.8 minimum (24x24)
1145
+ if (codeWidth < 24 || codeHeight < 24) {
1146
+ discrepancies.push({
1147
+ category: "accessibility",
1148
+ property: "targetSize",
1149
+ severity: "critical",
1150
+ designValue: `${Math.round(designWidth)}x${Math.round(designHeight)}`,
1151
+ codeValue: `${codeWidth}x${codeHeight}`,
1152
+ message: `Code renders below WCAG 2.5.8 minimum (24x24px): ${codeWidth}x${codeHeight}px`,
1153
+ suggestion: "Increase touch target size to at least 24x24px",
1154
+ });
1155
+ }
1156
+ }
1157
+ }
1158
+ // ---- 9. Keyboard Interactions ----
1159
+ if (ca.keyboardInteractions && ca.keyboardInteractions.length > 0 && !descLower.includes("keyboard")) {
1160
+ discrepancies.push({
1161
+ category: "accessibility",
1162
+ property: "keyboardInteractions",
1163
+ severity: "info",
1164
+ designValue: null,
1165
+ codeValue: ca.keyboardInteractions.join(", "),
1166
+ message: `Code defines keyboard interactions (${ca.keyboardInteractions.join(", ")}) but design has no keyboard documentation`,
1167
+ suggestion: "Document keyboard interactions in the Figma component description for developer handoff",
1168
+ });
1169
+ }
1016
1170
  }
1017
1171
  function compareNaming(node, codeSpec, discrepancies) {
1018
1172
  const cm = codeSpec.metadata;
@@ -2023,7 +2177,11 @@ const codeSpecSchema = z.object({
2023
2177
  keyboardInteractions: z.array(z.string()).optional(),
2024
2178
  contrastRatio: z.number().optional(),
2025
2179
  focusVisible: z.boolean().optional(),
2026
- }).optional().describe("Accessibility properties from code"),
2180
+ semanticElement: z.string().optional().describe("Semantic HTML element (e.g., 'button', 'a', 'input')"),
2181
+ supportsDisabled: z.boolean().optional().describe("Whether code supports disabled/aria-disabled state"),
2182
+ supportsError: z.boolean().optional().describe("Whether code supports aria-invalid/error state"),
2183
+ renderedSize: z.tuple([z.number(), z.number()]).optional().describe("Rendered size [width, height] in px"),
2184
+ }).optional().describe("Accessibility properties from code. Tip: use figma_scan_code_accessibility with mapToCodeSpec:true to auto-generate this from component HTML."),
2027
2185
  metadata: z.object({
2028
2186
  name: z.string().optional(),
2029
2187
  description: z.string().optional(),