Skip to main content

figmalint-design-system-auditing

AI-powered Figma plugin for auditing components for design system compliance, accessibility, and developer readiness

الانتقال إلى التثبيت

معلومات المصدر

المستودع
reason-machines/design-skills
آخر نشاط في المصدر
١٨ مايو ٢٠٢٦ في ١٣:٤٨
لغة SKILL.md المكتشفة
الإنجليزية
النجوم
٤
التفرعات
٠

خيارات التثبيت

يُحدَّد Prompt الذي يراجع المصدر أولًا بشكل افتراضي. يمكنك التبديل إلى أمر مباشر أو تنزيل نسخة محلية.

مراجعة ملفات المصدر

اقرأ SKILL.md وأي ملفات مرافقة يعرضها SkillsMP قبل أن تقرر التثبيت.

عرض SKILL.md

SKILL.md
تعليمات المصدر · معاينة للقراءة فقط
name
figmalint-design-system-auditing
description
AI-powered Figma plugin for auditing components for design system compliance, accessibility, and developer readiness
triggers
["audit my Figma component for design system compliance","analyze Figma components for accessibility issues","detect design tokens and hard-coded values in Figma","generate component documentation from Figma","fix design token usage in Figma components","export Figma component specs for developers","check Figma component readiness score","integrate FigmaLint into my workflow"]
# FigmaLint Design System Auditing Skill > Skill by [ara.so](https://ara.so) — Design Skills collection ## Overview FigmaLint is an AI-powered Figma plugin that audits components for design system compliance, accessibility standards (WCAG), and developer handoff readiness. It analyzes components, detects design tokens vs hard-coded values, identifies missing interactive states, and generates structured documentation for developer handoff or AI code generation. **Key capabilities:** - Multi-provider AI analysis (Anthropic Claude, OpenAI GPT, Google Gemini) - Design token detection and auto-fix binding - Accessibility auditing (contrast, touch targets, focus indicators) - Component state coverage analysis - Auto-fix for tokens and layer naming - Export to Markdown, AI Prompt, or JSON ## Installation ### From Figma Community ```bash # Install directly from Figma Community # Visit: https://www.figma.com/community/plugin/1521241390290871981/figmalint # Click "Install" button ``` ### Development Installation ```bash # Clone the repository git clone https://github.com/southleft/figmalint.git cd figmalint # Install dependencies npm install # Build the plugin npm run build # In Figma Desktop App: # Plugins > Development > Import plugin from manifest # Select manifest.json from the project root ``` ### Development Commands ```bash npm run dev # Development build with watch mode npm run build # Production build npm run lint # TypeScript type checking npm run clean # Clean build artifacts ``` ## Architecture Overview FigmaLint follows a modular architecture: ``` src/ ├── code.ts # Plugin entry point ├── types.ts # TypeScript definitions ├── api/ │ ├── claude.ts # Prompt construction │ └── providers/ # AI provider implementations │ ├── anthropic.ts │ ├── openai.ts │ └── google.ts ├── core/ │ ├── component-analyzer.ts # Component analysis │ ├── token-analyzer.ts # Token detection │ └── consistency-engine.ts # Design system checks ├── fixes/ │ ├── token-fixer.ts # Auto-fix token binding │ └── naming-fixer.ts # Layer renaming └── utils/ └── figma-helpers.ts # Figma API utilities ``` ## Configuration ### API Provider Setup FigmaLint supports three AI providers. Set up API keys using environment variables: ```typescript // API keys are stored in Figma's local storage per provider // Never hardcode keys in code // For Anthropic Claude process.env.ANTHROPIC_API_KEY // For OpenAI GPT process.env.OPENAI_API_KEY // For Google Gemini process.env.GOOGLE_API_KEY ``` ### Provider Configuration ```typescript // src/api/providers/types.ts export interface AIProvider { id: string; name: string; models: AIModel[]; call: (request: AIRequest) => Promise<AIResponse>; parseKey?: (key: string) => boolean; } // Available providers const PROVIDERS = { anthropic: { models: ['claude-opus-4.5', 'claude-sonnet-4.5', 'claude-haiku-4.5'] }, openai: { models: ['gpt-5.2', 'gpt-5.2-pro', 'gpt-5-mini'] }, google: { models: ['gemini-3-pro', 'gemini-2.5-pro', 'gemini-2.5-flash'] } }; ``` ## Core Functionality ### Component Analysis ```typescript // src/core/component-analyzer.ts import { analyzeComponent } from './core/component-analyzer'; // Analyze a Figma component async function analyzeComponentNode(node: ComponentNode) { const analysis = await analyzeComponent(node, { includeTokens: true, includeAccessibility: true, includeStates: true, includeNaming: true }); return { metadata: analysis.metadata, tokens: analysis.tokenAnalysis, states: analysis.statesCoverage, accessibility: analysis.accessibilityChecks, readiness: analysis.readinessScore }; } ``` ### Token Detection ```typescript // src/core/token-analyzer.ts import { analyzeTokens } from './core/token-analyzer'; interface TokenAnalysis { tokensByType: { colors: Array<{ name: string; value: string; boundNodes: string[] }>; spacing: Array<{ name: string; value: number; boundNodes: string[] }>; typography: Array<{ name: string; fontFamily: string; fontSize: number }>; effects: Array<{ name: string; type: string }>; borders: Array<{ name: string; strokeWeight: number }>; }; hardCodedValues: { colors: Array<{ nodeId: string; value: string; property: string }>; spacing: Array<{ nodeId: string; value: number; property: string }>; }; tokenAdoptionRate: number; } async function detectTokens(node: ComponentNode): Promise<TokenAnalysis> { return analyzeTokens(node, { includeLocalVariables: true, includeLibraryVariables: true, includeStyles: true, deduplicatePerNode: true }); } ``` ### Auto-Fix Token Binding ```typescript // src/fixes/token-fixer.ts import { bindHardCodedValueToToken } from './fixes/token-fixer'; interface TokenBindingOptions { searchLocal: boolean; searchLibraries: boolean; fuzzyMatch: boolean; propertyAwareScoring: boolean; } // Bind a hard-coded color to a design token async function fixColorToken(nodeId: string, hardCodedColor: string) { const result = await bindHardCodedValueToToken({ nodeId, property: 'fills', hardCodedValue: hardCodedColor, tokenType: 'color', options: { searchLocal: true, searchLibraries: true, fuzzyMatch: true, propertyAwareScoring: true } }); if (result.success) { console.log(`Bound to token: ${result.tokenName}`); } } // Bind spacing values async function fixSpacingToken(nodeId: string, hardCodedSpacing: number) { await bindHardCodedValueToToken({ nodeId, property: 'paddingLeft', hardCodedValue: hardCodedSpacing, tokenType: 'spacing', options: { searchLocal: true, searchLibraries: true, fuzzyMatch: true, propertyAwareScoring: true } }); } ``` ### Layer Naming Auto-Fix ```typescript // src/fixes/naming-fixer.ts import { suggestLayerName, applyLayerRename } from './fixes/naming-fixer'; type NamingStrategy = 'semantic' | 'bem' | 'prefix' | 'kebab' | 'camel' | 'snake'; // Detect generic names and suggest semantic alternatives async function fixLayerNaming(node: SceneNode, strategy: NamingStrategy = 'semantic') { const suggestion = suggestLayerName(node, strategy); if (suggestion.isGeneric) { console.log(`Generic name detected: "${suggestion.currentName}"`); console.log(`Suggested: "${suggestion.suggestedName}"`); // Apply the rename await applyLayerRename(node.id, suggestion.suggestedName); } } // Recognizes 30+ semantic layer types: // icon, button, label, badge, avatar, card, header, footer, // navigation, sidebar, modal, dropdown, input, checkbox, etc. ``` ### Accessibility Auditing ```typescript // Accessibility checks included in component analysis interface AccessibilityChecks { contrastRatio: { pass: boolean; ratio: number; wcagLevel: 'AA' | 'AAA' | 'fail'; }; touchTargets: { pass: boolean; minSize: number; actualSize: { width: number; height: number }; }; focusIndicators: { pass: boolean; hasVisibleFocus: boolean; }; fontSize: { pass: boolean; minSize: number; actualSize: number; }; } async function checkAccessibility(node: ComponentNode) { const analysis = await analyzeComponent(node); const { accessibilityChecks } = analysis; if (!accessibilityChecks.contrastRatio.pass) { console.warn(`Contrast ratio: ${accessibilityChecks.contrastRatio.ratio} (fail)`); } if (!accessibilityChecks.touchTargets.pass) { console.warn(`Touch target too small: ${accessibilityChecks.touchTargets.actualSize.width}x${accessibilityChecks.touchTargets.actualSize.height}`); } } ``` ### Component State Detection ```typescript // Detect missing interactive states interface StatesCoverage { detected: string[]; missing: string[]; variants: Array<{ name: string; properties: Record<string, string>; }>; } async function checkComponentStates(node: ComponentSetNode) { const analysis = await analyzeComponent(node); const { statesCoverage } = analysis; console.log('Detected states:', statesCoverage.detected); // Example: ['default', 'hover', 'pressed'] console.log('Missing states:', statesCoverage.missing); // Example: ['focus', 'disabled', 'active'] // Interactive states checked: // hover, focus, disabled, pressed, active, selected, error, loading } ``` ### AI-Powered Description Generation ```typescript // Generate structured component description interface ComponentDescription { summary: string; sections: { purpose: string; behavior: string; composition: string; usage: string; codeGenerationNotes: string; }; nestedComponents: string[]; currentDescription: string; matches: boolean; } async function generateDescription(node: ComponentNode, provider: string, model: string, apiKey: string) { const prompt = buildDescriptionPrompt(node); const response = await callAIProvider({ provider, model, apiKey, prompt, systemPrompt: 'You are a design systems expert generating component documentation.' }); return { summary: response.summary, sections: response.sections, nestedComponents: response.nestedComponents, matches: node.description === response.generatedDescription }; } ``` ### Export Formats ```typescript // Export component documentation type ExportFormat = 'markdown' | 'ai-prompt' | 'json'; async function exportComponent(node: ComponentNode, format: ExportFormat) { const analysis = await analyzeComponent(node); switch (format) { case 'markdown': // Comprehensive documentation for design system sites return generateMarkdownExport(analysis); case 'ai-prompt': // Structured spec for AI code generation return generateAIPromptExport(analysis); case 'json': // Complete analysis data for programmatic use return JSON.stringify(analysis, null, 2); } } // Markdown export includes: // - Component metadata and variants table // - Properties API reference // - Interactive states (pass/fail status) // - Design token breakdown (tokens vs hard-coded) // - Accessibility audit results // - Component readiness score // - AI interpretation ``` ### Design Systems Chat ```typescript // Multi-turn conversational interface interface ChatMessage { role: 'user' | 'assistant'; content: string; timestamp: number; } interface ChatContext { componentId: string; analysis: ComponentAnalysis; conversationHistory: ChatMessage[]; } async function askAboutComponent(question: string, context: ChatContext) { const prompt = buildChatPrompt(question, context); const response = await callAIProvider({ provider: context.provider, model: context.model, apiKey: process.env[`${context.provider.toUpperCase()}_API_KEY`], prompt, conversationHistory: context.conversationHistory }); // Update conversation history context.conversationHistory.push( { role: 'user', content: question, timestamp: Date.now() }, { role: 'assistant', content: response, timestamp: Date.now() } ); return response; } ``` ## Common Patterns ### Full Component Audit Workflow ```typescript async function auditComponent(componentNode: ComponentNode) { // 1. Analyze component const analysis = await analyzeComponent(componentNode, { includeTokens: true, includeAccessibility: true, includeStates: true, includeNaming: true }); // 2. Check readiness score console.log(`Readiness Score: ${analysis.readinessScore}/100`); // 3. Identify issues const issues = []; if (analysis.tokenAnalysis.hardCodedValues.colors.length > 0) { issues.push(`${analysis.tokenAnalysis.hardCodedValues.colors.length} hard-coded colors`); } if (analysis.statesCoverage.missing.length > 0) { issues.push(`Missing states: ${analysis.statesCoverage.missing.join(', ')}`); } if (!analysis.accessibilityChecks.contrastRatio.pass) { issues.push('Contrast ratio fails WCAG standards'); } // 4. Auto-fix issues if (analysis.tokenAnalysis.hardCodedValues.colors.length > 0) { for (const hardCoded of analysis.tokenAnalysis.hardCodedValues.colors) { await bindHardCodedValueToToken({ nodeId: hardCoded.nodeId, property: hardCoded.property, hardCodedValue: hardCoded.value, tokenType: 'color' }); } } // 5. Export documentation const markdown = await exportComponent(componentNode, 'markdown'); const aiPrompt = await exportComponent(componentNode, 'ai-prompt'); return { analysis, issues, markdown, aiPrompt }; } ``` ### Batch Token Fixing ```typescript async function fixAllTokens(componentNode: ComponentNode) { const analysis = await analyzeComponent(componentNode); const { hardCodedValues } = analysis.tokenAnalysis; // Fix all hard-coded colors for (const color of hardCodedValues.colors) { await bindHardCodedValueToToken({ nodeId: color.nodeId, property: color.property, hardCodedValue: color.value, tokenType: 'color', options: { searchLocal: true,
عرض على GitHub
ملف SKILL.md هذا كبير جدا، لذلك يعرض SkillsMP القسم الاول فقط هنا. عرض على GitHub