Claude Code Plugins

Community-maintained marketplace

Feedback

figma-v3-migration-plugin-dev

@daangn/seed-design
806
0

Figma V3 Migration Plugin development specialist. Use when developing Figma V3 Migration Plugin. Focuses on Figma V3 Migration Plugin development.

Install Skill

1Download skill
2Enable skills in Claude

Open claude.ai/settings/capabilities and find the "Skills" section

3Upload to Claude

Click "Upload skill" and select the downloaded ZIP file

Note: Please verify skill by going through its instructions before using it.

SKILL.md

name figma-v3-migration-plugin-dev
description Figma V3 Migration Plugin development specialist. Use when developing Figma V3 Migration Plugin. Focuses on Figma V3 Migration Plugin development.
allowed-tools Read, Write, Edit, MultiEdit, Bash, Glob, Grep

개요

Figma V3 Migration 플러그인은 SEED Design System V2 컴포넌트를 V3로 마이그레이션하는 Figma 플러그인입니다.

디렉토리 구조

tools/figma-v3-migration/
├── src/main/
│   ├── mapping/                    # 매핑 정의 파일들
│   │   ├── types.ts                # 타입 정의
│   │   ├── index.ts                # 모든 매핑 export
│   │   ├── buttons.ts              # 버튼 컴포넌트 매핑
│   │   ├── action-sheet.ts         # Action Sheet 매핑
│   │   └── [component].ts          # 기타 컴포넌트별 매핑
│   ├── data/
│   │   └── __generated__/          # 자동 생성된 메타데이터
│   │       ├── v2-component-sets/  # V2 컴포넌트 메타데이터
│   │       └── v3-component-sets/  # V3 컴포넌트 메타데이터
│   └── services/                   # Figma API 서비스
├── figma-extractor.config.ts       # 추출 설정
└── package.json

환경 설정

1. 환경변수 설정

export FIGMA_PERSONAL_ACCESS_TOKEN="your-figma-token"

Figma Personal Access Token은 Figma Settings > Account > Personal access tokens에서 생성할 수 있습니다.

2. 의존성 설치

cd tools/figma-v3-migration
bun install

매핑 최신화 프로세스

1. 메타데이터 추출

cd tools/figma-v3-migration
bun extract

이 명령어는 Figma API에서 V3 컴포넌트 메타데이터를 추출하여 src/main/data/__generated__/v3-component-sets/ 디렉토리에 .d.ts 파일로 저장합니다.

2. 변경된 파일 확인

git status
git diff src/main/data/__generated__/

3. 매핑 파일 업데이트 워크플로우

  1. 변경된 Generated 파일 분석: 새로 추가되거나 변경된 컴포넌트 확인
  2. 관련 매핑 파일 수정: src/main/mapping/ 디렉토리의 해당 컴포넌트 매핑 업데이트
  3. index.ts 업데이트: 새 매핑 추가 시 export 목록에 추가
  4. 타입 체크: bun run typecheck:main으로 매핑 파일 타입 에러 확인

매핑 파일 작성 가이드

기본 구조

매핑 파일은 ComponentMapping<OldComponentName, NewComponentName> 타입을 사용합니다.

import type { ComponentMapping, NewComponentProperties } from "./types";

export const exampleMapping: ComponentMapping<"Old Component Name", "New Component Name"> = {
  oldComponent: "Old Component Name",    // V2 컴포넌트 이름 (Generated 파일의 name과 일치)
  newComponent: "New Component Name",    // V3 컴포넌트 이름
  variantMap: {
    // Variant 값 매핑
  },
  calculateProperties(oldProperties) {
    // 프로퍼티 변환 로직
    const newProperties: NewComponentProperties<"New Component Name"> = {};
    return newProperties;
  },
};

실제 예제: buttons.ts

// tools/figma-v3-migration/src/main/mapping/buttons.ts

import type { ComponentMapping, NewComponentProperties } from "./types";

export const boxButtonMapping: ComponentMapping<"✅ Box Button v2", "🟢 Action Button"> = {
  oldComponent: "✅ Box Button v2",
  newComponent: "🟢 Action Button",

  // 1. variantMap: Variant 값 매핑
  variantMap: {
    // 형식: "VariantName:OldValue": "VariantName:NewValue"
    "Size:XSmall": "Size:Small",
    "Size:Small": "Size:Small",
    "Size:Medium": "Size:Medium",
    "Size:Large": "Size:Large",
    "Size:XLarge": "Size:Large",
    "State:Enabled": "State:Enabled",
    "State:Disabled": "State:Disabled",
    "State:Loading": "State:Loading",
    "State:Pressed": "State:Pressed",
    "Variant:Primary": "Variant:Neutral Solid",
    "Variant:Primary low": "Variant:Neutral Weak",
    "Variant:Secondary": "Variant:Neutral Weak",
    "Variant:Danger": "Variant:Critical Solid",
  },

  // 2. calculateProperties: 프로퍼티 변환 로직
  calculateProperties(oldProperties) {
    const newProperties: NewComponentProperties<"🟢 Action Button"> = {
      // TEXT 프로퍼티 매핑: "PropertyName#NodeId"
      "Label#5987:61": oldProperties["Label#28272:77"].value,
    };

    // BOOLEAN 프로퍼티 읽기
    const prefixIcon = oldProperties["Prefix icon#28272:78"].value;
    const suffixIcon = oldProperties["Suffix icon#28272:76"].value;

    // 조건부 로직으로 Layout 설정
    if (prefixIcon && suffixIcon) {
      newProperties.Layout = "Icon Last";
      newProperties["Prefix Icon#5987:305"] = oldProperties["↳Icons#28292:0"].value;
    } else if (prefixIcon) {
      newProperties.Layout = "Icon First";
      newProperties["Prefix Icon#5987:305"] = oldProperties["↳Icons#28292:0"].value;
    } else if (suffixIcon) {
      newProperties.Layout = "Icon Last";
    } else {
      newProperties.Layout = "Text Only";
    }

    return newProperties;
  },
};

중첩 컴포넌트 처리: action-sheet.ts

부모 컴포넌트 내부에 자식 컴포넌트가 있는 경우 childrenMappings를 사용합니다.

// tools/figma-v3-migration/src/main/mapping/action-sheet.ts

import type { ComponentMapping, NewComponentProperties } from "./types";

// 자식 컴포넌트 매핑 정의
const itemMenuGroupMapping: ComponentMapping<"Action button group", ".Item / Menu Group"> = {
  oldComponent: "Action button group",
  newComponent: ".Item / Menu Group",
  variantMap: {},
  calculateProperties(oldProperties) {
    const newProperties: NewComponentProperties<".Item / Menu Group"> = {
      "Action Count":
        oldProperties["Action count"].value === "8 (Max)"
          ? "8"
          : oldProperties["Action count"].value,
    };
    return newProperties;
  },
};

const itemMenuItemMapping: ComponentMapping<"Action button", ".Item / Menu Item"> = {
  oldComponent: "Action button",
  newComponent: ".Item / Menu Item",
  variantMap: {
    "State:Default": "State:Enabled",
    "State:Pressed": "State:Pressed",
    "Type:Destructive": "Tone:Critical",
    "Type:Enabled": "Tone:Neutral",
    "Prefix icon:True": "Layout:Text with Icon",
    "Prefix icon:False": "Layout:\bText Only",
  },
  calculateProperties(oldProperties) {
    const newProperties: NewComponentProperties<".Item / Menu Item"> = {
      "Label#55905:8": oldProperties["🅃 Action label#55905:8"].value,
    };

    const hasPrefixIcon = oldProperties["Prefix icon"].value === "True";
    if (hasPrefixIcon) {
      newProperties["Show Prefix Icon#17043:5"] = true;
      newProperties["Prefix Icon#55948:0"] = oldProperties["Icon#55948:0"].value;
    }

    return newProperties;
  },
};

// 부모 컴포넌트 매핑 (childrenMappings 포함)
export const actionSheetMapping: ComponentMapping<"✅ Action Sheet v2", "🟢 Menu Sheet"> = {
  oldComponent: "✅ Action Sheet v2",
  newComponent: "🟢 Menu Sheet",
  variantMap: {},
  calculateProperties(oldProperties) {
    const newProperties: NewComponentProperties<"🟢 Menu Sheet"> = {
      Layout: "Text Only",
      "Show Safe Area#25531:15": true,
      "Menu Group Count": "1",
    };

    const hasTitle = oldProperties.Title.value === "True";
    if (hasTitle) {
      newProperties["Show Header#17043:12"] = true;
    }

    return newProperties;
  },
  // 자식 컴포넌트 매핑 배열
  childrenMappings: [itemMenuGroupMapping, itemMenuItemMapping],
};

새 매핑 추가 시 체크리스트

  1. Generated 파일 확인

    • V2: src/main/data/__generated__/v2-component-sets/[component].d.ts
    • V3: src/main/data/__generated__/v3-component-sets/[component].d.ts
  2. 매핑 파일 생성/수정

    • src/main/mapping/[component].ts 파일 생성 또는 기존 파일에 추가
  3. index.ts 업데이트

    // src/main/mapping/index.ts
    import { newComponentMapping } from "./new-component";
    
    export default [
      // ... 기존 매핑들
      newComponentMapping,
    ] as const;
    
  4. 타입 체크

    cd tools/figma-v3-migration
    bun run typecheck:main  # 매핑 파일 타입 체크
    bun run typecheck       # 전체 타입 체크 (main + ui)
    

타입 시스템

Generated 메타데이터 구조

// src/main/data/__generated__/v3-component-sets/action-button.d.ts
export declare const metadata: {
  "name": "🟢 Action Button",
  "key": "450ede9d0bf42fc6ef14345c77e6e407d6d5ee89",
  "componentPropertyDefinitions": {
    "Label#5987:61": {
      "type": "TEXT",
      "defaultValue": "라벨"
    },
    "Size": {
      "type": "VARIANT",
      "defaultValue": "XSmall",
      "variantOptions": ["XSmall", "Small", "Medium", "Large"]
    },
    "Layout": {
      "type": "VARIANT",
      "defaultValue": "Text Only",
      "variantOptions": ["Text Only", "Icon First", "Icon Last", "Icon Only"]
    },
    "Prefix Icon#5987:305": {
      "type": "INSTANCE_SWAP",
      "defaultValue": "37665:153410",
      "preferredValues": []
    }
  }
};

프로퍼티 타입별 처리

타입 설명 값 형식
VARIANT 선택 가능한 옵션들 variantOptions 중 하나
TEXT 텍스트 입력 string
BOOLEAN 참/거짓 boolean
INSTANCE_SWAP 컴포넌트 교체 컴포넌트 key (string)

타입 안전성

ComponentMapping 타입은 Generated 메타데이터를 기반으로 타입 검증을 수행합니다:

  • 컴포넌트 이름: V2/V3 Generated 파일의 name과 일치해야 함
  • 프로퍼티 키: "PropertyName#NodeId" 형식으로 정확히 일치해야 함
  • Variant 값: variantOptions에 정의된 값만 사용 가능

잘못된 프로퍼티 이름이나 값을 사용하면 TypeScript 컴파일 에러가 발생합니다.

트러블슈팅

일반적인 에러

1. "Property does not exist" 타입 에러

원인: 프로퍼티 이름이 Generated 파일과 일치하지 않음

해결: Generated .d.ts 파일에서 정확한 프로퍼티 이름 확인

cat src/main/data/__generated__/v3-component-sets/[component].d.ts

2. "Type is not assignable" 에러

원인: Variant 값이 variantOptions에 없는 값

해결: Generated 파일의 variantOptions 확인 후 올바른 값 사용

3. Extract 명령어 실패

원인: FIGMA_PERSONAL_ACCESS_TOKEN 미설정 또는 만료

해결:

export FIGMA_PERSONAL_ACCESS_TOKEN="new-token"
bun extract

디버깅 팁

  1. 프로퍼티 이름 확인

    # V2 컴포넌트 프로퍼티 확인
    cat src/main/data/__generated__/v2-component-sets/[component].d.ts
    
    # V3 컴포넌트 프로퍼티 확인
    cat src/main/data/__generated__/v3-component-sets/[component].d.ts
    
  2. 기존 매핑 패턴 참고

    # 비슷한 컴포넌트의 매핑 확인
    cat src/main/mapping/buttons.ts
    cat src/main/mapping/checkbox.ts
    
  3. 타입 에러 확인

    cd tools/figma-v3-migration
    bun run typecheck:main  # 매핑 파일만 체크
    bun run typecheck       # 전체 체크