Token导航 LogoToken导航TokenDH.com
研究检索需要联网github未标认证来源可访问clear审计通过

figma-designFigma 设计

Agent Skill

用于辅助界面设计、视觉规范、排版、配色、布局和交互体验优化。它适合让 Agent 根据产品场景整理页面结构、生成 UI 方案、检查视觉一致性或改进组件层级。使用时需要结合现有品牌、设计系统和用户任务,不应只堆装饰元素;涉及真实页面改动时,应通过截图或浏览器预览检查文本溢出、对齐和响应式表现。

总安装

4,218

周安装

174

GitHub Stars

54

下载量

1,378
CodexClaudeCursorGemini CLI

安装说明

本站只整理中文说明和来源信息,不托管安装包,也不代用户安装。

GitHub

来源数

3

许可证

MIT

最后核验

2026-05-01

来源状态

来源可访问

安装方式

通过对话安装

复制提示词发给支持本地命令或 Skills 的 AI 助手,先确认命令和权限,再让它执行。

请帮我安装这个 Agent Skill:figma-design(Figma 设计)
来源仓库:https://github.com/manutej/luxor-claude-marketplace
仓库路径:skills/figma-design
安装命令:
npx skills add https://github.com/manutej/luxor-claude-marketplace --skill figma-design
安装前请先检查当前环境是否支持对应 CLI,并向我确认将要执行的命令、安装目录、联网范围和文件读写权限;确认后再执行。

命令行安装

复制命令到本机终端执行。不同来源提供的安装方式可能略有差异;本站展示可直接复制的安装命令,安装前请核对来源页面。

skills.shnpx skills
npx skills add https://github.com/manutej/luxor-claude-marketplace --skill figma-design

简介

构建 Figma 插件和管理设计系统的开发工具集。

  • 涵盖组件管理、自动布局、变量操作和原型设计。
  • 支持节点搜索、样式管理和性能优化实践。
  • 安装命令:npx skills add https://github.com/manutej/luxor-claude-marketplace --skill figma-design。
  • 适用于插件开发和自动化设计流程场景。

SKILL.md

Figma Design Skill

Comprehensive guide for Figma design workflows, plugin development, component systems, auto layout, prototyping, and design system management based on official Figma Plugin API documentation from Context7.

When to Use This Skill

Use this skill when working with:

  • Figma Plugin Development: Building custom plugins, UI extensions, automation tools
  • Design Systems: Creating and managing variables, styles, components, and libraries
  • Component Architecture: Building reusable components, variants, and instances
  • Auto Layout: Implementing responsive frames with constraints and spacing
  • Prototyping: Creating interactive prototypes with reactions and flows
  • Batch Operations: Automating repetitive design tasks across multiple nodes
  • Export & Integration: Exporting assets in various formats (PNG, JPG, SVG)
  • Data Management: Storing and retrieving plugin/shared data on nodes
  • Collaboration: Managing version history, comments, and team workflows

Core Concepts

1. Figma Node Hierarchy

The Figma document structure is a tree of nodes:

DocumentNode (root)
└── PageNode
    ├── FrameNode
    │   ├── TextNode
    │   ├── RectangleNode
    │   └── ComponentNode
    └── SectionNode
        └── FrameNode

Key Node Types:

  • FRAME: Container with auto-layout capabilities
  • COMPONENT: Reusable design element (master)
  • INSTANCE: Copy of a component
  • TEXT: Editable text layer
  • RECTANGLE, ELLIPSE, POLYGON, STAR, LINE: Basic shapes
  • SECTION: Organizational container for frames
  • GROUP: Non-layout container

2. Components and Instances

Components are master elements that can be instantiated multiple times:

// Create a component
const button = figma.createComponent()
button.name = "Primary Button"
button.resize(120, 40)

// Add visual elements
const bg = figma.createRectangle()
bg.resize(120, 40)
bg.cornerRadius = 8
bg.fills = [{ type: 'SOLID', color: { r: 0.2, g: 0.5, b: 1 } }]
button.appendChild(bg)

// Create instance
const buttonInstance = button.createInstance()
buttonInstance.x = 200
buttonInstance.y = 100

Component Properties:

  • BOOLEAN: Toggle visibility or states
  • TEXT: Customizable text content
  • INSTANCE_SWAP: Swap nested components
  • VARIANT: Different component variations

3. Auto Layout

Auto Layout creates responsive frames that adapt to content changes:

Core Properties:

  • layoutMode: 'HORIZONTAL', 'VERTICAL', or 'NONE'
  • primaryAxisSizingMode: 'FIXED' or 'AUTO'
  • counterAxisSizingMode: 'FIXED' or 'AUTO'
  • paddingLeft, paddingRight, paddingTop, paddingBottom
  • itemSpacing: Gap between children
  • primaryAxisAlignItems: Alignment on main axis
  • counterAxisAlignItems: Alignment on cross axis

Constraints for Children:

  • minWidth, maxWidth: Width boundaries
  • minHeight, maxHeight: Height boundaries
  • layoutAlign: 'MIN', 'CENTER', 'MAX', 'STRETCH'
  • layoutGrow: 0 (fixed) or 1 (fill container)
// Create auto-layout frame
const frame = figma.createFrame()
frame.layoutMode = 'VERTICAL'
frame.primaryAxisSizingMode = 'AUTO'
frame.counterAxisSizingMode = 'FIXED'
frame.resize(300, 0) // Width fixed, height auto
frame.itemSpacing = 16
frame.paddingLeft = 24
frame.paddingRight = 24
frame.paddingTop = 24
frame.paddingBottom = 24

// Add children with constraints
const child = figma.createRectangle()
child.resize(252, 100)
child.layoutAlign = 'STRETCH' // Fill width
child.minHeight = 100
child.maxHeight = 200
frame.appendChild(child)

4. Constraints

Constraints control how nodes resize when their parent changes:

interface Constraints {
  horizontal: 'MIN' | 'CENTER' | 'MAX' | 'STRETCH' | 'SCALE'
  vertical: 'MIN' | 'CENTER' | 'MAX' | 'STRETCH' | 'SCALE'
}

node.constraints = {
  horizontal: 'MIN',    // Pin to left
  vertical: 'MAX'       // Pin to bottom
}

Constraint Types:

  • MIN: Pin to top/left edge
  • CENTER: Center in parent
  • MAX: Pin to bottom/right edge
  • STRETCH: Scale with parent (both edges)
  • SCALE: Maintain proportional position and size

5. Variables and Design Tokens

Variables create dynamic design systems (Figma Design only):

// Create variable collection
const collection = figma.variables.createVariableCollection('Design Tokens')

// Create color variable
const primaryColor = figma.variables.createVariable(
  'color/primary',
  collection,
  'COLOR'
)

// Set value for default mode
const defaultMode = collection.modes[0]
primaryColor.setValueForMode(defaultMode.modeId, {
  r: 0.2, g: 0.5, b: 1, a: 1
})

// Add dark mode
const darkMode = collection.addMode('Dark')
primaryColor.setValueForMode(darkMode, {
  r: 0.4, g: 0.7, b: 1, a: 1
})

// Create variable alias (reference)
const accentColor = figma.variables.createVariable(
  'color/accent',
  collection,
  'COLOR'
)
const alias = figma.variables.createVariableAlias(primaryColor)
accentColor.setValueForMode(defaultMode.modeId, alias)

// Bind variable to node
const rect = figma.createRectangle()
const fill = { type: 'SOLID', color: { r: 0, g: 0, b: 0 } } as SolidPaint
const boundFill = figma.variables.setBoundVariableForPaint(
  fill,
  'color',
  primaryColor
)
rect.fills = [boundFill]

Variable Types:

  • COLOR: RGB/RGBA values
  • FLOAT: Numeric values (spacing, sizes)
  • BOOLEAN: True/false flags
  • STRING: Text values

6. Styles

Styles define reusable visual properties:

// Paint style (fills/strokes)
const paintStyle = figma.createPaintStyle()
paintStyle.name = 'Brand/Primary'
paintStyle.paints = [{
  type: 'SOLID',
  color: { r: 0.2, g: 0.5, b: 1 }
}]

// Text style
const textStyle = figma.createTextStyle()
textStyle.name = 'Heading/H1'
textStyle.fontSize = 32
textStyle.fontName = { family: 'Inter', style: 'Bold' }
textStyle.lineHeight = { value: 120, unit: 'PERCENT' }
textStyle.letterSpacing = { value: -0.5, unit: 'PIXELS' }

// Effect style (shadows, blurs)
const effectStyle = figma.createEffectStyle()
effectStyle.name = 'Shadow/Card'
effectStyle.effects = [{
  type: 'DROP_SHADOW',
  color: { r: 0, g: 0, b: 0, a: 0.15 },
  offset: { x: 0, y: 4 },
  radius: 8,
  visible: true,
  blendMode: 'NORMAL'
}]

// Apply styles
rect.fillStyleId = paintStyle.id
text.textStyleId = textStyle.id
frame.effectStyleId = effectStyle.id

Prototyping

1. Reactions and Interactions

Reactions define interactive behavior in prototypes:

// Set reactions on a node
await node.setReactionsAsync([
  {
    action: {
      type: 'NODE',
      destinationId: 'nodeId', // Target frame
      navigation: 'NAVIGATE',
      transition: {
        type: 'SMART_ANIMATE',
        easing: { type: 'EASE_IN_AND_OUT' },
        duration: 0.3
      },
      preserveScrollPosition: false
    },
    trigger: {
      type: 'ON_CLICK'
    }
  }
])

Trigger Types:

  • ON_CLICK: Click/tap
  • ON_HOVER: Mouse hover
  • ON_PRESS: Touch press
  • ON_DRAG: Drag interaction
  • MOUSE_ENTER, MOUSE_LEAVE, MOUSE_UP, MOUSE_DOWN
  • AFTER_TIMEOUT: Delayed trigger

Navigation Types:

  • NAVIGATE: Go to destination
  • SWAP: Swap overlay
  • OVERLAY: Open as overlay
  • SCROLL_TO: Scroll to position
  • CHANGE_TO: Change to state

2. Overlay Configuration

Control how frames appear as overlays:

frame.overlayPositionType // 'CENTER' | 'TOP_LEFT' | 'TOP_CENTER' | etc.
frame.overlayBackground // How overlay obscures background
frame.overlayBackgroundInteraction // Click-through behavior

3. Scrolling Frames

Configure frame scrolling behavior:

frame.overflowDirection = 'VERTICAL_SCROLLING' // or 'HORIZONTAL_SCROLLING'
frame.numberOfFixedChildren = 1 // First N children stay fixed during scroll

Plugin Development

1. Plugin Structure

Basic Plugin Files:

my-plugin/
├── manifest.json       # Plugin configuration
├── code.ts            # Main plugin logic
└── ui.html            # Optional UI

manifest.json:

{
  "name": "My Plugin",
  "id": "unique-plugin-id",
  "api": "1.0.0",
  "main": "code.js",
  "ui": "ui.html",
  "editorType": ["figma", "figjam"],
  "documentAccess": "dynamic-page",
  "networkAccess": {
    "allowedDomains": ["api.example.com"]
  }
}

2. Plugin Lifecycle

// Initialize plugin
async function init() {
  // Show UI (optional)
  figma.showUI(__html__, {
    width: 400,
    height: 500,
    title: "My Plugin",
    themeColors: true
  })

  // Load saved preferences
  const prefs = await figma.clientStorage.getAsync('preferences')

  // Send initial data to UI
  figma.ui.postMessage({
    type: 'init',
    data: prefs
  })
}

// Handle UI messages
figma.ui.onmessage = async (msg) => {
  if (msg.type === 'create-shapes') {
    await createShapes(msg.count, msg.color)
  }

  if (msg.type === 'export') {
    await exportSelection()
  }
}

// Clean up on close
figma.on('close', () => {
  console.log('Plugin closing...')
})

// Start plugin
init()

3. UI Communication

Send message from plugin to UI:

figma.ui.postMessage({
  type: 'selection-changed',
  count: figma.currentPage.selection.length,
  nodes: figma.currentPage.selection.map(n => ({
    id: n.id,
    name: n.name,
    type: n.type
  }))
})

Receive messages in UI (ui.html):

<script>
  window.onmessage = (event) => {
    const msg = event.data.pluginMessage

    if (msg.type === 'selection-changed') {
      document.getElementById('count').textContent = msg.count
    }
  }

  // Send message to plugin
  function createShapes() {
    parent.postMessage({
      pluginMessage: {
        type: 'create-shapes',
        count: 5,
        color: { r: 1, g: 0, b: 0 }
      }
    }, '*')
  }
</script>

4. Event Listeners

Monitor document and selection changes:

// Selection changes
figma.on('selectionchange', () => {
  const selection = figma.currentPage.selection
  console.log(`Selected ${selection.length} nodes`)
})

// Document changes
figma.on('documentchange', (event) => {
  for (const change of event.documentChanges) {
    if (change.type === 'CREATE') {
      console.log(`Created: ${change.id}`)
    }

    if (change.type === 'DELETE') {
      console.log(`Deleted: ${change.id}`)
    }

    if (change.type === 'PROPERTY_CHANGE') {
      console.log(`Changed properties: ${change.properties.join(', ')}`)
    }
  }
})

// Page changes
figma.on('currentpagechange', () => {
  console.log(`Now on page: ${figma.currentPage.name}`)
})

5. Data Storage

Plugin Data (private to your plugin):

// Store data on node
node.setPluginData('status', 'approved')
node.setPluginData('metadata', JSON.stringify({
  author: 'John',
  tags: ['important']
}))

// Retrieve data
const status = node.getPluginData('status')
const metadata = JSON.parse(node.getPluginData('metadata') || '{}')

// List all keys
const keys = node.getPluginDataKeys()

Shared Plugin Data (accessible by namespace):

// Store shared data
node.setSharedPluginData('com.example.plugin', 'version', '2.0')

// Retrieve shared data
const version = node.getSharedPluginData('com.example.plugin', 'version')

// List shared keys
const keys = node.getSharedPluginDataKeys('com.example.plugin')

Client Storage (persistent settings):

// Save preferences
await figma.clientStorage.setAsync('preferences', {
  theme: 'dark',
  lastUsed: new Date().toISOString()
})

// Load preferences
const prefs = await figma.clientStorage.getAsync('preferences')

// Delete data
await figma.clientStorage.deleteAsync('preferences')

// List all keys
const keys = await figma.clientStorage.keysAsync()

Finding Nodes

1. Optimized Search with findAllWithCriteria

FASTEST method for large documents (hundreds of times faster):

// Enable performance optimization
figma.skipInvisibleInstanceChildren = true

// Find by type
const textNodes = figma.currentPage.findAllWithCriteria({
  types: ['TEXT']
})

// Find multiple types
const shapes = figma.currentPage.findAllWithCriteria({
  types: ['RECTANGLE', 'ELLIPSE', 'POLYGON']
})

// Find nodes with plugin data
const nodesWithStatus = figma.currentPage.findAllWithCriteria({
  pluginData: {
    keys: ['status']
  }
})

// Find nodes with shared plugin data
const nodesWithSharedData = figma.currentPage.findAllWithCriteria({
  sharedPluginData: {
    namespace: 'com.example.plugin',
    keys: ['version']
  }
})

// Combine criteria
const textWithData = figma.currentPage.findAllWithCriteria({
  types: ['TEXT'],
  pluginData: {} // Any plugin data
})

2. Traditional Search Methods

// Find all matching nodes
const frames = figma.currentPage.findAll(node => node.type === 'FRAME')

// Find first match
const template = figma.currentPage.findOne(node =>
  node.name.startsWith('Template')
)

// Find by ID
const node = await figma.getNodeByIdAsync('123:456')

// Recursive tree traversal
function walkTree(node: BaseNode) {
  console.log(`${node.type}: ${node.name}`)

  if ('children' in node) {
    for (const child of node.children) {
      walkTree(child)
    }
  }
}

walkTree(figma.currentPage)

Export and Image Handling

1. Export Nodes

// Export as PNG
const pngBytes = await node.exportAsync({
  format: 'PNG',
  constraint: { type: 'SCALE', value: 2 } // 2x resolution
})

// Export as JPG
const jpgBytes = await node.exportAsync({
  format: 'JPG',
  constraint: { type: 'SCALE', value: 1 },
  contentsOnly: false // Include background
})

// Export as SVG
const svgBytes = await node.exportAsync({
  format: 'SVG',
  svgIdAttribute: true,
  svgOutlineText: false,
  svgSimplifyStroke: true
})

// Export with fixed dimensions
const thumbnail = await node.exportAsync({
  format: 'PNG',
  constraint: { type: 'WIDTH', value: 200 }
})

// Export with height constraint
const preview = await node.exportAsync({
  format: 'PNG',
  constraint: { type: 'HEIGHT', value: 400 }
})

2. Load Images

// Load from URL
const image = await figma.createImageAsync('https://example.com/image.png')
const { width, height } = await image.getSizeAsync()

// Create rectangle with image
const rect = figma.createRectangle()
rect.resize(width, height)
rect.fills = [{
  type: 'IMAGE',
  imageHash: image.hash,
  scaleMode: 'FILL' // or 'FIT', 'CROP', 'TILE'
}]

// Load from bytes
function loadFromBytes(bytes: Uint8Array) {
  const image = figma.createImage(bytes)
  return image
}

// Create from SVG string
const svgString = `
  <svg width="100" height="100">
    <circle cx="50" cy="50" r="40" fill="#3366ff"/>
  </svg>
`
const node = figma.createNodeFromSvg(svgString)

Text Handling

1. Text Basics

// Create text (MUST load font first)
const text = figma.createText()
await figma.loadFontAsync(text.fontName) // Load default font

// Set content
text.characters = 'Hello World'

// Change font
await figma.loadFontAsync({ family: 'Inter', style: 'Bold' })
text.fontName = { family: 'Inter', style: 'Bold' }

// Styling
text.fontSize = 24
text.lineHeight = { value: 150, unit: 'PERCENT' }
text.letterSpacing = { value: 0, unit: 'PIXELS' }
text.textAlignHorizontal = 'CENTER'
text.textAlignVertical = 'CENTER'
text.textCase = 'UPPER' // or 'LOWER', 'TITLE', 'ORIGINAL'
text.textDecoration = 'UNDERLINE' // or 'STRIKETHROUGH', 'NONE'

2. Rich Text Formatting

// Apply formatting to range
text.setRangeFontSize(0, 5, 32) // First 5 chars = 32px
text.setRangeFills(0, 5, [{
  type: 'SOLID',
  color: { r: 1, g: 0, b: 0 }
}])

// Get font at position
const fontName = text.getRangeFontName(0, 1)
const fontSize = text.getRangeFontSize(0, 1)

Resizing and Transforms

1. Resizing Methods

// Resize with constraints applied
node.resize(300, 200)

// Resize without constraints
node.resizeWithoutConstraints(300, 200)

// Scale proportionally
node.rescale(1.5) // 150% scale

2. Transforms

// Position
node.x = 100
node.y = 200

// Relative to parent
console.log(node.relativeTransform) // [[1,0,x], [0,1,y]]

// Absolute position on page
console.log(node.absoluteTransform)

// Bounding box
const bounds = node.absoluteBoundingBox
// { x: number, y: number, width: number, height: number }

Collaboration Features

1. Comments

While plugins can't create comments via API, they can:

  • Navigate to frames with comments
  • Read comment metadata via REST API
  • Trigger notifications

2. Version History

// Plugin data can track custom versioning
node.setPluginData('version', '2.1.0')
node.setPluginData('lastModified', new Date().toISOString())
node.setPluginData('modifiedBy', 'user@example.com')

3. Team Libraries

// Check if node is from external library
if (node.type === 'INSTANCE') {
  const component = node.mainComponent
  if (component && component.parent?.type === 'PAGE') {
    // Component is from library
  }
}

Best Practices from Context7

1. Performance Optimization

// ✅ Use findAllWithCriteria for large documents
const nodes = figma.currentPage.findAllWithCriteria({
  types: ['TEXT']
})

// ❌ Avoid findAll for simple type searches
const nodes = figma.currentPage.findAll(n => n.type === 'TEXT')

// ✅ Enable invisible instance optimization
figma.skipInvisibleInstanceChildren = true

// ✅ Batch operations
const nodes = []
for (let i = 0; i < 100; i++) {
  const rect = figma.createRectangle()
  rect.x = i * 120
  nodes.push(rect)
}
figma.currentPage.selection = nodes
figma.viewport.scrollAndZoomIntoView(nodes)

// ❌ Avoid individual viewport updates
for (let i = 0; i < 100; i++) {
  const rect = figma.createRectangle()
  figma.viewport.scrollAndZoomIntoView([rect]) // Slow!
}

2. Font Loading

// ✅ Always load fonts before modifying text
const text = figma.createText()
await figma.loadFontAsync(text.fontName)
text.characters = 'Hello'

// ✅ Load font before changing fontName
await figma.loadFontAsync({ family: 'Roboto', style: 'Bold' })
text.fontName = { family: 'Roboto', style: 'Bold' }

// ❌ This will error
text.characters = 'Hello' // Error: font not loaded

3. Error Handling

try {
  const node = await figma.getNodeByIdAsync(id)
  if (!node) {
    figma.notify('Node not found', { error: true })
    return
  }

  // Process node
} catch (error) {
  figma.notify(`Error: ${error.message}`, { error: true })
  console.error(error)
}

4. Memory Management

// ✅ Clean up large data
figma.on('close', () => {
  // Clear large caches
  cache.clear()
})

// ✅ Use async iteration for large datasets
async function processManyNodes() {
  const nodes = figma.currentPage.findAllWithCriteria({ types: ['TEXT'] })

  for (let i = 0; i < nodes.length; i++) {
    await processNode(nodes[i])

    // Yield to UI every 100 items
    if (i % 100 === 0) {
      await new Promise(resolve => setTimeout(resolve, 0))
    }
  }
}

5. Type Safety

// ✅ Type guards
if (node.type === 'TEXT') {
  // TypeScript knows node is TextNode
  console.log(node.characters)
}

if ('children' in node) {
  // Node has children
  node.children.forEach(child => console.log(child.name))
}

// ✅ Use specific types
function processText(node: TextNode) {
  console.log(node.characters)
}

// ❌ Avoid any
function processNode(node: any) { // Bad!
  console.log(node.characters) // Might error
}

Common Workflows

1. Design System Setup

async function setupDesignSystem() {
  // Create variable collection
  const tokens = figma.variables.createVariableCollection('Design Tokens')

  // Colors
  const colors = {
    'color/primary': { r: 0.2, g: 0.5, b: 1, a: 1 },
    'color/secondary': { r: 0.5, g: 0.2, b: 0.8, a: 1 },
    'color/success': { r: 0.2, g: 0.8, b: 0.3, a: 1 },
    'color/error': { r: 0.9, g: 0.2, b: 0.2, a: 1 }
  }

  for (const [name, value] of Object.entries(colors)) {
    const variable = figma.variables.createVariable(name, tokens, 'COLOR')
    variable.setValueForMode(tokens.modes[0].modeId, value)
  }

  // Spacing
  const spacing = [4, 8, 12, 16, 24, 32, 48, 64]
  spacing.forEach((value, i) => {
    const variable = figma.variables.createVariable(
      `spacing/${i}`,
      tokens,
      'FLOAT'
    )
    variable.setValueForMode(tokens.modes[0].modeId, value)
  })

  // Create styles
  const primaryStyle = figma.createPaintStyle()
  primaryStyle.name = 'Color/Primary'
  primaryStyle.paints = [{
    type: 'SOLID',
    color: colors['color/primary']
  }]

  figma.notify('Design system created!')
}

2. Component Library

async function createButtonLibrary() {
  // Create component set for variants
  const buttons = figma.createComponentSet()
  buttons.name = "Button"

  // Primary variant
  const primary = figma.createComponent()
  primary.name = "Type=Primary, Size=Medium"
  primary.resize(120, 40)
  buttons.appendChild(primary)

  // Secondary variant
  const secondary = figma.createComponent()
  secondary.name = "Type=Secondary, Size=Medium"
  secondary.resize(120, 40)
  buttons.appendChild(secondary)

  // Large size
  const large = figma.createComponent()
  large.name = "Type=Primary, Size=Large"
  large.resize(160, 48)
  buttons.appendChild(large)

  return buttons
}

3. Batch Export

async function exportAllFrames() {
  const frames = figma.currentPage.findAllWithCriteria({
    types: ['FRAME']
  })

  const exports = []

  for (const frame of frames) {
    // Export 1x and 2x
    const bytes1x = await frame.exportAsync({
      format: 'PNG',
      constraint: { type: 'SCALE', value: 1 }
    })

    const bytes2x = await frame.exportAsync({
      format: 'PNG',
      constraint: { type: 'SCALE', value: 2 }
    })

    exports.push({
      name: frame.name,
      '1x': bytes1x,
      '2x': bytes2x
    })
  }

  // Send to UI for download
  figma.ui.postMessage({
    type: 'exports-ready',
    exports
  })
}

4. Style Sync

async function syncStyles() {
  const paintStyles = await figma.getLocalPaintStylesAsync()
  const textStyles = await figma.getLocalTextStylesAsync()

  // Update all instances
  const nodes = figma.currentPage.findAllWithCriteria({
    types: ['RECTANGLE', 'TEXT']
  })

  for (const node of nodes) {
    if (node.type === 'RECTANGLE') {
      // Apply paint style based on name
      const style = paintStyles.find(s => s.name === 'Brand/Primary')
      if (style) {
        node.fillStyleId = style.id
      }
    }

    if (node.type === 'TEXT') {
      // Apply text style
      const style = textStyles.find(s => s.name === 'Body/Regular')
      if (style) {
        node.textStyleId = style.id
      }
    }
  }

  figma.notify('Styles synced!')
}

Plugin UI Patterns

1. Theme-Aware UI

<!DOCTYPE html>
<html>
<head>
  <style>
    body {
      margin: 0;
      padding: 16px;
      font-family: 'Inter', sans-serif;
      background: var(--figma-color-bg);
      color: var(--figma-color-text);
    }

    button {
      background: var(--figma-color-bg-brand);
      color: var(--figma-color-text-onbrand);
      border: none;
      padding: 8px 16px;
      border-radius: 6px;
      cursor: pointer;
      font-size: 14px;
    }

    button:hover {
      background: var(--figma-color-bg-brand-hover);
    }

    input {
      background: var(--figma-color-bg);
      color: var(--figma-color-text);
      border: 1px solid var(--figma-color-border);
      padding: 8px;
      border-radius: 4px;
    }
  </style>
</head>
<body>
  <h2>My Plugin</h2>
  <input type="text" id="input" placeholder="Enter text...">
  <button onclick="handleClick()">Create</button>
</body>
</html>

2. Loading States

<div id="status">
  <div class="spinner"></div>
  <p>Processing...</p>
</div>

<script>
  function showLoading() {
    document.getElementById('status').style.display = 'block'
  }

  function hideLoading() {
    document.getElementById('status').style.display = 'none'
  }

  async function process() {
    showLoading()
    parent.postMessage({ pluginMessage: { type: 'process' } }, '*')
  }

  window.onmessage = (event) => {
    if (event.data.pluginMessage.type === 'complete') {
      hideLoading()
    }
  }
</script>

FigJam-Specific Features

if (figma.editorType === 'figjam') {
  // Create sticky note
  const sticky = figma.createSticky()
  sticky.x = 100
  sticky.y = 100
  await figma.loadFontAsync({ family: "Roboto", style: "Regular" })
  sticky.text.characters = "TODO: Review designs"

  // Create connector
  const connector = figma.createConnector()
  connector.connectorStart = {
    endpointNodeId: sticky.id,
    position: { x: 0, y: 0.5 }
  }

  // Create shape
  const shape = figma.createShape()
  shape.resize(100, 100)
  shape.fills = [{ type: 'SOLID', color: { r: 1, g: 0.8, b: 0 } }]
}

Advanced Techniques

1. Smart Component Swapping

async function swapComponents(oldComponent: ComponentNode, newComponent: ComponentNode) {
  const instances = figma.currentPage.findAllWithCriteria({
    types: ['INSTANCE']
  })

  let swapCount = 0

  for (const instance of instances) {
    if (instance.mainComponent?.id === oldComponent.id) {
      await instance.swapAsync(newComponent)
      swapCount++
    }
  }

  figma.notify(`Swapped ${swapCount} instances`)
}

2. Auto Layout Migration

function convertToAutoLayout(frame: FrameNode) {
  // Store original positions
  const childData = frame.children.map(child => ({
    node: child,
    x: child.x,
    y: child.y
  }))

  // Enable auto layout
  frame.layoutMode = 'VERTICAL'
  frame.primaryAxisSizingMode = 'AUTO'
  frame.counterAxisSizingMode = 'FIXED'
  frame.itemSpacing = 16
  frame.paddingLeft = 24
  frame.paddingRight = 24
  frame.paddingTop = 24
  frame.paddingBottom = 24

  // Configure children
  frame.children.forEach(child => {
    if ('layoutAlign' in child) {
      child.layoutAlign = 'STRETCH'
    }
  })
}

3. Responsive Resize

function makeResponsive(frame: FrameNode) {
  frame.layoutMode = 'VERTICAL'
  frame.primaryAxisSizingMode = 'AUTO'
  frame.counterAxisSizingMode = 'FIXED'

  // Make children responsive
  frame.children.forEach(child => {
    if ('resize' in child) {
      child.layoutAlign = 'STRETCH'
      child.layoutGrow = 0
      child.minWidth = 200
      child.maxWidth = 800
    }
  })
}

Testing and Debugging

// Console logging
console.log('Selection:', figma.currentPage.selection)
console.error('Error occurred:', error)

// Notifications
figma.notify('Success!', { timeout: 2000 })
figma.notify('Error occurred', { error: true })

// Debugging helpers
function debugNode(node: SceneNode) {
  console.log('Node Debug Info:')
  console.log('  Type:', node.type)
  console.log('  Name:', node.name)
  console.log('  ID:', node.id)
  console.log('  Position:', { x: node.x, y: node.y })

  if ('width' in node) {
    console.log('  Size:', { width: node.width, height: node.height })
  }

  if ('children' in node) {
    console.log('  Children:', node.children.length)
  }
}

Resources

Summary

This skill covers:

  • Component and instance management
  • Auto layout and constraints
  • Variables and design tokens
  • Styles (paint, text, effect)
  • Prototyping and interactions
  • Plugin development patterns
  • Node search and manipulation
  • Export and image handling
  • Performance optimization
  • Best practices from Context7 research

Use this skill for building production-ready Figma plugins, automating design workflows, managing design systems, and creating scalable component libraries.

适合场景

01

用户想查找某类 Agent Skill 时

02

需要根据任务场景推荐可安装能力包时

03

需要对比不同来源的安装命令和来源信息时

04

需要参考平台分布和安装热度时

能力概览

能力 1

按任务关键词查找相关 Skills

能力 2

展示可复制的安装命令

能力 3

保留来源站点、仓库和原始说明,方便继续核验

能力 4

补充不同宿主或平台的使用分布数据

能力 5

展示第三方安全扫描或审计结果

安装后应在对应宿主中按原始 README 的触发条件使用;具体调用方式请以来源页面和 README 为准。

平台分布

Claude Code

28.83%
按下载量换算397

Cursor

20.49%
按下载量换算282

Gemini CLI

15.49%
按下载量换算213

windsurf

12.1%
按下载量换算167

Antigravity

7.83%
按下载量换算108

OpenCode

3.61%
按下载量换算50

安全审计

Gen Agent Trust Hub

通过

Socket

通过

Snyk

通过

权限和风险

需要联网

该 Skill 可能需要联网访问来源站点、仓库或外部 API;具体网络访问范围需要结合源码和 README 复核。

安装前确认

本站仅展示第三方公开信息,不托管安装包,不提供自动安装或运行环境。安装前应自行审查源码、依赖和命令行为。

来源信息

继续浏览同类 Skills