figma-v3-migration-plugin-dev | Skill Performance & Reviews | TopRankSkills

TopRank Skills

Home / Skills / tools / figma-v3-migration-plugin-dev

figma-v3-migration-plugin-dev

maintained by daangn

star 815 account_tree 40 verified_user MIT License
bolt View GitHub

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       # 전체 체크
    

chat Comments (0)

chat_bubble_outline

No comments yet. Be the first to share your thoughts!

Skill Details

GitHub Stars 815
GitHub Forks 40
Created Jan 2026
Last Updated 5个月前
tools tools productivity tools

Related Skills

ui-ux-pro-max
chevron_right
planning-with-files
chevron_right
agent-browser
chevron_right
building-agents
chevron_right
prisma-expert
chevron_right

Build your own?

Join 12,000+ developers contributing to the Claude ecosystem.