mcpField
C
cc-figma-component

cc-figma-component

github.com/nvillapianoデザイン・UI3369 回インストール31 週間前に更新
リポジトリ

cc-figma-component について

cc-figma-componentは、コンポーネント契約からFigmaのコンポーネントセットを生成するスキルです。契約に沿ってコンポーネント固有トークンを導出し、バリアントや構成を反映してFigma変数に紐付けます。

主な機能

  1. 01コンポーネント契約の読み込み
  2. 02コンポーネント固有トークンの導出
  3. 03Semantic変数へのプロパティ紐付け
  4. 04バリアント軸と状態に基づくセット作成
  5. 05契約で定義されたコンポーネント構成の適用

活用シーン

  1. 01契約からFigmaコンポーネントを生成
  2. 02プロパティと状態に基づくバリアントセット作成
  3. 03コンポーネントの見た目をSemantic変数で管理

MCP 対応

Figmaの`use_figma`呼び出しを使い、Figmaファイル内のページやコンポーネントの確認・作成、変数の紐付けを行います。

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/nvillapiano/component-contracts-figma --skill cc-figma-component

インストール後、Claude Code で/cc-figma-componentを入力して読み込まれたか確認します。

詳細

cc-figma-component — コンポーネントコントラクト コンポーネントスキル

コンポーネントコントラクトから Figma のコンポーネントセットを生成します。このスキルはコントラクトを読み取り、コンポーネントスコープ(Tier 3)のトークンを導出し、Figma 内で完全に変数にバインドされたコンポーネントセットを構築します。

前提条件 — 先にこれらのスキルを読み込んでください:

  • figma-use — Plugin API の構文ルール(すべての use_figma 呼び出しの前に必須)
  • figma-generate-library — デザインシステムのワークフローとコンポーネント作成パターン
  • cc-figma-tokens が実行済みであること — 対象の Figma ファイルに Primitives コレクションと Semantic コレクションが存在している必要があります

このスキルの一環として use_figma を呼び出す際は、常に skillNames: "cc-figma-component" を渡してください。


グローバルルール

フレームのサイズ設定はデフォルトで HUG

このスキルで作成されるすべてのフレームは、作成直後に両方のサイズプロパティを 'HUG' に設定する必要があります — 例外はありません。

node.layoutSizingHorizontal = 'HUG';
node.layoutSizingVertical   = 'HUG';

これは次に適用されます: ベースコンポーネントフレーム、すべてのバリアントの複製、Generation Notes フレーム、および実行中に作成されるその他すべてのフレーム。Figma のデフォルトに依存しないでください — 新しいフレームは FIXED の 100px に設定され、パディングの値に関係なく縦長のコンポーネントが生成されます。HUG から逸脱するのは、スロットの子の figma.sizing がコントラクトで明示的に "fixed" に設定されている場合のみです。その場合は、コントラクトの figma.width と figma.height の値を直接使用します:

if (child.figma?.sizing === 'fixed') {
  node.layoutSizingHorizontal = 'FIXED';
  node.layoutSizingVertical   = 'FIXED';
  node.resize(child.figma.width, child.figma.height);
}

これが HUG デフォルトに対する唯一の正当な例外です。


1. 設定

何よりも先に、プロジェクトルートから .component-contracts を読み取ってください。どのような応答においても FIGMA_ACCESS_TOKEN を出力しないでください。

FIGMA_ACCESS_TOKEN=...       # never output this value
FIGMA_FILE_KEY=...           # use for all use_figma calls
TOKENS_DIR=...               # root directory of token files
CONTRACTS_DIR=...            # root directory of contract files

2. コントラクトの構造

コンポーネントコントラクトは {CONTRACTS_DIR}/{id}.contract.json にある JSON ファイルです。何かを計画する前に、完全に読み取ってください。

このスキルが使用する主要なセクション:

tokens — コンポーネントの Tier 3 トークンバインディングをカテゴリ別に定義します:

{
  "tokens": {
    "color": {
      "background.primary": "brand.500",
      "text.primary": "neutral.0",
      "border.secondary": "brand.500"
    },
    "spacing": {
      "padding.x.sm": "space.sm",
      "padding.y.sm": "space.xs"
    },
    "typography": {
      "label.size": "textSize.sm",
      "label.weight": "weight.semibold"
    },
    "border": {
      "radius": "radius.md",
      "width": "border.width.sm"
    },
    "motion": {
      "transition": "duration.fast"
    }
  }
}

props — コンポーネントのバリアント軸(例: variant、size、state)を定義します

a11y — アクセシビリティ要件(ARIA ロール、キーボードの動作)

platforms — 対象プラットフォーム(web、ios、android)


3. Tier 3 トークンの導出

コンポーネントスコープ(Tier 3)のトークンは、コントラクトの tokens セクションから導出されます — 別のファイルとして保存されるものではありません。以下のルールを使用して実行時に導出してください:

命名規則
--ds-{componentId}-{role}-{qualifier}

ここで:

  • componentId — コントラクトの id フィールド(例: button、accordion)
  • role — Figma に合わせたロール名(以下のロール変換表を参照)
  • qualifier — コントラクトの値にある Semantic エイリアス名から導出されます
ロール変換表
コントラクトのカテゴリ + キープレフィックスCSS/Figma ロール
color.background.*fill
color.text.*text
color.border.*border
color.focus.*focus
spacing.*spacing
typography.*typography
border.radiusborder(border-radius として)
border.widthborder(border-width として)
motion.*transition
修飾子の導出

修飾子はコントラクトの Semantic エイリアス値から取得し、スケールのサフィックスを除いたものです:

"background.primary": "brand.500"   →  qualifier = "brand"   →  --ds-button-fill-brand
"background.primary.hover": "brand.600"  →  qualifier = "brand-hover"
"text.primary": "neutral.0"         →  qualifier = "neutral-0"

状態のサフィックス(hover、active、focus、disabled)は修飾子の後に付加されます:

--ds-button-fill-brand-hover
--ds-button-fill-brand-active
Semantic 変数の検索

各 Tier 3 トークンは、Figma 内の対応する Semantic 変数にバインドする必要があります。変数を名前で検索してください:

contract value "brand.500"  →  Semantic variable named "brand/500"
contract value "space.sm"   →  Semantic variable named "space/sm"
contract value "radius.md"  →  Semantic variable named "radius/md"

Semantic 変数が見つからない場合は、処理を続ける前に停止し、不足している変数をユーザーに報告してください。


4. コンポーネントセットのアーキテクチャ

プライマリバリアントプロパティ(例: variant)の各値は、単一の統合セットではなく、別々のコンポーネントセットになります。セカンダリ軸(Size、State)は各セット内のバリアントプロパティになります。

命名規則
{ComponentName}/{VariantValue}   →   Button/Primary, Accordion/Multiple
  • コンポーネント名: タイトルケース(Button、Accordion)
  • バリアント値: タイトルケース(Primary、Secondary)
  • 区切り文字: /
各コンポーネントセット内のバリアント軸

プライマリバリアント以外のすべての軸は、コンポーネントセット内のプロパティになります。

Button/Primary:
  Size=Small,  State=Default
  Size=Small,  State=Hover
  Size=Small,  State=Focus
  Size=Small,  State=Active
  Size=Small,  State=Disabled
  Size=Small,  State=Loading
  Size=Medium, State=Default
  ... (18 total variants per set)
プロパティの命名
  • プロパティ名: タイトルケース、コントラクトのプロパティ名と一致させる(Size、State)
  • プロパティ値: タイトルケース(Small、Medium、Large、Default、Hover、Focus、Active、Disabled、Loading)
標準の状態値

状態は必ずコントラクトの states 配列から読み取ってください — ハードコードされたリストは使用しないでください。Figma のプロパティ値では、各値をタイトルケースにします(例: "default" → "Default")。コンポーネントごとに状態のセットは異なります — Button は Loading を含む 6 つ、Accordion は Loading のない 5 つです。


5. 実行モード

デフォルト(高速): すべてのフェーズを停止せずに順番に実行します。Phase 0 の計画を提示して承認を待ち、その後 Phase 1〜7 を中断なく実行します。これがすべての実行におけるデフォルトです。

デバッグモード: 各フェーズの後に停止し、続行する前に明示的な承認を待ちます。問題を診断する場合や中間出力を検証する場合に使用します。プロンプトに「debug mode」を含めることで有効になります。スクリプトはデバッグモードでのみ保持されます — 完了したら手動でクリーンアップしてください。

スクリプトの場所: すべての作業ファイルは scripts/ サブディレクトリに書き込まなければなりません — リポジトリのルートには決して書き込まないでください。ルートレベルのドットファイル(.mcp-args-phase3.json、.phase2-code-raw.js など)は rimraf ステップではクリーンアップされず、リポジトリに蓄積されます。

Note: scripts/ を .gitignore に追加してください — これらは生成された作業ファイルであり、ソース成果物ではありません。


6. ワークフロー

Phase 0 — ディスカバリー(読み取り専用)
  1. .component-contracts 設定を読み取る
  2. CONTRACTS_DIR からコントラクトファイルを読み取る
  3. Figma ファイルを検査する — 既存の Semantic/Primitive コレクションと、この名前の既存コンポーネントがあるか確認する
  4. Semantic コレクションと Primitive コレクションが存在することを確認する — 存在しない場合は停止し、最初に cc-figma-tokens を実行するようユーザーに伝える
  5. コントラクトの tokens セクションから完全な Tier 3 トークンリストを導出する
  6. すべての Semantic 変数を検索する — 続行する前にすべてが存在することを確認する
  7. コントラクトの props セクションから完全なバリアントマトリクスを構築する
  8. 完全な計画をユーザーに提示する:
    • コンポーネント名とバリアント数
    • Semantic エイリアスを含む完全な Tier 3 トークンリスト
    • 不足している Semantic 変数
  9. デバッグモードの場合: 続行する前にユーザーの明示的な承認を待つ
Phase 1 — ページのセットアップ
  1. コンポーネント専用のページを作成する: {ComponentName}(例: Button、Accordion)
  2. await figma.setCurrentPageAsync(page) でそのページに切り替える
  3. ページ ID を返す
フェーズ 2 — ベースコンポーネント

まず 1 つのベースコンポーネント(プライマリバリアントの Default 状態)を構築します:

  1. 自動レイアウト、水平方向の Frame を作成します
  2. 作成直後に、次の正確な 2 行を使ってサイズを HUG に設定します — どちらも必須で、片方だけでは不十分です:
    frame.layoutSizingHorizontal = 'HUG';
    frame.layoutSizingVertical   = 'HUG';
    
    Figma は新しいフレームをデフォルトで FIXED の 100px にします。垂直方向の行を省略すると、パディング値に関係なく縦長のボタンが生成されます。子ノードやバインディングを追加する前にこれを行ってください。
  3. すべての構造プロパティ(パディング、ギャップ、半径)を Semantic 変数にバインドして適用します
  4. コントラクトの composition.slots セクションを読んで子ノードを追加します。childOrder を使ってレンダリング順序を決定します — 固定の順序を仮定しないでください:
    • composition.slots.{slotName}.childOrder を読み取ります — この配列はフレームに子が追加される順序を定義します
    • childOrder 内の各子について、その figma ヒントを読み取ります:
      • figma.textProp — テキストノードを作成し、そのコンポーネントプロパティ名に接続します
      • figma.booleanProp — アイコンプレースホルダーフレームを作成し、visible: false を設定し、その BOOLEAN プロパティ名に接続します
      • figma.position: "trailing" — この子は他の子に関係なく最後に配置されます
      • figma.rotateOnExpand — 回転は変数バインドできないことを Generation Notes に記載します
      • figma.visibleWhen — 可視性は状態駆動であることを Generation Notes に記載します
    • composition.slots が定義されていない場合は、次のフォールバックを使用します:アイコンプレースホルダー(非表示)、次にラベルテキストノード
    • アイコンプレースホルダーフレームは常に固定サイズ(md の場合は 20×20)、塗りなし、デフォルトで visible: false です
  5. すべての視覚プロパティを Semantic 変数にバインドします — ハードコードされた値は禁止です
  6. すべての子を追加した直後に、作成後のサイズチェックを実行します。 これは、minifier が HUG 割り当てを落とした可能性のあるフレームを修正します:
    // Walk every frame in the component subtree and enforce HUG
    function enforceHug(node) {
      if (node.type === 'FRAME' || node.type === 'COMPONENT') {
        if (node.layoutSizingVertical === 'FIXED') {
          node.layoutSizingHorizontal = 'HUG';
          node.layoutSizingVertical   = 'HUG';
        }
      }
      if ('children' in node) node.children.forEach(enforceHug);
    }
    enforceHug(baseComponent);
    
  7. すべてのノードに再帰的に setExplicitVariableModeForCollection を適用します
  8. 検証:get_screenshot — 続行する前に、ボタンが高さより幅が広いことを確認します
  9. デバッグモードの場合:ユーザーのチェックポイントを待機します
フェーズ 3 — バリアントマトリクス

プライマリバリアントプロパティの各値について、個別のコンポーネントセットを作成します:

  1. Size × State の組み合わせごとにベースコンポーネントを複製します
  2. すべての複製で、トークンオーバーライドを適用する前に、次の正確な 2 行を使ってサイズを HUG にリセットします:
    duplicate.layoutSizingHorizontal = 'HUG';
    duplicate.layoutSizingVertical   = 'HUG';
    
    複製は元のサイズモードを保持する場合がありますが、例外なくすべてのコピーでこれを明示的に再設定する必要があります。
  3. 状態ごとにバリアント固有のトークンオーバーライドを適用します(例:hover は塗り色を変更します)
  4. 各コンポーネントに名前を付けます:Size=Small, State=Default など(タイトルケース、Property=Value)
  5. combineAsVariants を呼び出す前に、すべてのバリアントフレームに対して HUG 強制パスを実行します。これはセーフティネットです — エージェントが見落としたフレームを捕捉します:
    variants.forEach(v => {
      v.layoutSizingHorizontal = 'HUG';
      v.layoutSizingVertical   = 'HUG';
    });
    
    このパスの後でも高さが 100px のままのバリアントは、サイズの問題ではなくバインディングの問題を示しています。
  6. combineAsVariants を呼び出してコンポーネントセットを作成します
  7. コンポーネントセットの名前を {ComponentName}/{VariantValue} に変更します(例:Button/Primary)
  8. combineAsVariants の直後に:バリアントを手動でグリッドレイアウトし、実際の境界に合わせてサイズ変更します:
    const COLS = 6; // one column per state
    const GAP = 40;
    const PADDING = 40; // padding inside component set on all sides
    
    variants.forEach((v, i) => {
      v.x = PADDING + (i % COLS) * (v.width + GAP);
      v.y = PADDING + Math.floor(i / COLS) * (v.height + GAP);
    });
    
    // Resize to actual content bounds — never guess, always calculate
    const maxRight = Math.max(...variants.map(v => v.x + v.width));
    const maxBottom = Math.max(...variants.map(v => v.y + v.height));
    componentSet.resize(maxRight + PADDING, maxBottom + PADDING);
    
  9. 各バリアント値(Primary、Secondary、Ghost、Destructive)について繰り返します
  10. 検証:get_screenshot — すべてのサイズでボタンが高さより幅が広いことを確認します
  11. デバッグモードの場合:ユーザーのチェックポイントを待機します
フェーズ 4 — 変数バインディングパス

すべてのバリアントノードについて:

  1. 塗りプロパティを正しい Semantic カラー変数にバインドします
  2. 線プロパティを正しい Semantic カラー変数にバインドします
  3. パディング/ギャップを正しい Semantic スペーシング変数にバインドします
  4. 角の半径を正しい Semantic 半径変数にバインドします
  5. バインド後に、すべてのノードとそのすべての子に再帰的に setExplicitVariableModeForCollection を呼び出します
  6. 検証:get_screenshot — 色が正しく解決されることを確認します(ゴースト化/未解決の変数がないこと)
フェーズ 5 — コンポーネントプロパティ
  1. コントラクトの props セクションに一致するコンポーネントプロパティを定義します:
    • TEXT label — Loading を含むすべてのバリアントで、Label テキストノードの characters にリンクします。「Saving」のようなハードコードされた文字列で絶対に代用しないでください。ラベルテキストは常に label プロパティの値によって駆動されます。
    • BOOLEAN iconStart — componentPropertyReferences を介して Icon プレースホルダーの visible プロパティにリンクします。デフォルトは false(非表示)です。これがアイコンスロットの表示・非表示を切り替える正しい方法です。
    • BOOLEAN iconOnly — コンポーネントセット上で定義します。レイアウトには自動的にリンクされません(既知の制約を参照)。
    • BOOLEAN fullWidth — コンポーネントセット上で定義します。レイアウトには自動的にリンクされません(既知の制約を参照)。
  2. disabled や loading を BOOLEAN プロパティとして追加しないでください — これらはバリアント状態としてのみ扱われます
  3. ファイル内に実在するアイコンコンポーネントが存在しない限り、アイコン用の INSTANCE_SWAP を追加しないでください
  4. 検証: プロパティパネルがコントラクトの props と一致することを確認します
フェーズ 6 — キャンバスの注釈

最終検証の前に、コンポーネントページ上に ⚠️ Generation Notes フレームを作成し、エージェントが想定したこと、フラグを立てたこと、解決できなかったことをすべて記録します。これにより、ファイルを開く誰にとっても出力が自己文書化されます。

このフレームは、すべてのコンポーネントセットの下に、明確に分離して配置してください。薄い黄色の塗り(#FFFBEB)、自動レイアウトの垂直方向を使用し、サイズを明示的に設定します:

notesFrame.layoutSizingHorizontal = 'HUG';
notesFrame.layoutSizingVertical   = 'HUG';

これにより、フレームは固定高さでクリップされるのではなく、すべての注記テキストを含むように拡張されます。タイトルのテキストノードを追加し、その後に個々の注記エントリを続けます。

該当する場合は、以下のそれぞれについて必ず注記を含めてください:

条件記述する注記
focus/default がバリアントの塗りと同じ色「フォーカスリングの色の競合: focus/default は [variant] の塗りの上で見えない可能性があります。focus/onBrand セマンティックトークンを定義して再実行してください。」
Loading 状態にスピナーコンポーネントがない「State=Loading: スピナーコンポーネントが見つかりません。ラベルテキストは保持されています。スピナーのインスタンスを追加して iconStart に接続するか、専用のローディングインジケーターを作成してください。」
Semantic ではなく Primitives にバインドされているトークンがある「トークンギャップ: [token name] にセマンティックエイリアスがありません。Primitives に直接バインドされています。トークンアーキテクチャに合わせるためにセマンティックエイリアスを追加してください。」
fullWidth または iconOnly がレイアウトに接続されていない「fullWidth / iconOnly はコンポーネントプロパティとして定義されていますが、レイアウトを自動的に駆動しません。既知の制約を参照してください。」
コントラクトに iconEnd プロパティが存在する「iconEnd は Figma でモデル化されていません — 末尾のアイコンスロットは作成されていません。2 つ目のアイコンプレースホルダーフレームを追加し、必要に応じて iconEnd BOOLEAN に接続してください。」
コントラクトのプロパティが Figma でモデル化されていない「コントラクトの [prop name] が Figma でモデル化されていません: [reason]。」
生成中に行われた想定明示的に文書化してください。

注記がない場合でも、フレームを作成し、「No issues — all tokens resolved, all props wired.」というテキストを記載してください。


フェーズ 7 — 最終検証
  1. get_metadata — 構造を確認します: バリアント数、プロパティ定義、階層
  2. get_screenshot — 視覚的チェック: ボタンはすべてのサイズで幅が高さより大きい、テキストがクリップされていない、要素が重なっていない、間隔が正しい、バリアントが切り取られていない
  3. 構造化されたサマリーを返します:
{
  "component": "Button",
  "componentSets": [
    { "name": "Button/Primary", "variantCount": 18, "id": "..." },
    { "name": "Button/Secondary", "variantCount": 18, "id": "..." },
    { "name": "Button/Ghost", "variantCount": 18, "id": "..." },
    { "name": "Button/Destructive", "variantCount": 18, "id": "..." }
  ],
  "propertiesDefined": ["Size", "State", "label", "iconStart", "iconOnly", "fullWidth"],
  "annotations": ["list of notes written to canvas"],
  "tier3Tokens": [...],
  "pageId": "..."
}
  1. クリーンアップ — 成功・失敗にかかわらず、毎回の実行の最後に必ずこれを実行してください。唯一の例外はデバッグモードです。

    スクリプトは使い捨てです。 保持、再利用、再生成を提案しないでください。ユーザーに terser の実行や invoke ファイルの書き換えを指示しないでください。毎回の実行で、まっさらな状態から新しいセットが生成されます。これらはソース成果物ではなく、ビルドキャッシュとして扱ってください。

    scripts/ ディレクトリと、リポジトリルートに書き込まれた作業ファイルを削除します:

    npx rimraf scripts/
    rm -f .mcp-*.json .mcp-*.txt .*-phase*.js .*-phase*.json .*-args*.json .*-code*.js .*-code*.json .tmp-*.js
    

    デバッグモードでは、検査のためにすべてのファイルをそのまま残してください。


7. 変数バインディングのルール

  • コンポーネントはセマンティック変数にのみバインドします — プリミティブに直接バインドしてはいけません
  • 対応するトークンを持つすべての視覚プロパティは変数にバインド MUST — ハードコードされた値は使用しないでください
  • 変数バインディング操作の後は、すべてのノード AND すべての子ノードに対して再帰的に setExplicitVariableModeForCollection を呼び出す MUST
  • テキストノードに対する setBoundVariable は、先にフォントを読み込む必要があります: await figma.loadFontAsync({family, style})
  • cornerRadius は setBoundVariable を直接サポートしていません — 個別の角を使用してください: topLeftRadius、topRightRadius、bottomLeftRadius、bottomRightRadius
  • 常に setSharedPluginData / getSharedPluginData を使用してください — setPluginData / getPluginData は決して使用しないでください。非共有バージョンは、ツール実行ごとに変化するデバッグ UUID をプラグイン識別子として使用するため、保存されたデータが永久に取得できなくなり、ファイルが肥大化します。常に component_contracts 名前空間を使用してください:
    // CORRECT
    node.setSharedPluginData('component_contracts', 'dsb_key', 'component/button/base');
    node.getSharedPluginData('component_contracts', 'dsb_key');
    
    // WRONG — UUID changes per execution, data becomes orphaned
    node.setPluginData('dsb_key', 'component/button/base');
    

8. 既知の制約

  • フレームのサイズ設定はデフォルトで FIXED、100px — Figma では新しいフレームは高さ 100px の FIXED サイズ設定になります。すべてのフレーム、すべてのバリアントの複製、そして Generation Notes フレームで、両方の行を明示的に設定する必要があります:

    node.layoutSizingHorizontal = 'HUG';
    node.layoutSizingVertical   = 'HUG';
    

    水平方向のみを設定し、垂直方向を省略することが、縦長アスペクトのボタンができる最も一般的な原因です。省略記法はありません — 常に両方の行が必要です。

  • レタースペーシング — 変数にバインドすることはできません(em 単位は Figma の FLOAT と互換性がありません)。トークンの生の値から導出した固定のピクセル値として設定してください。

  • combineAsVariants は自動レイアウトを行いません — バリアントは (0,0) に積み重なります。常に直後に手動でグリッドレイアウトを行ってください。常に、すべてのバリアントの位置 + サイズ + パディングに対して Math.max を使って、コンポーネントセットを実際のコンテンツの境界にリサイズしてください。リサイズの寸法を推測してはいけません。

  • layoutSizingHorizontal/Vertical = 'FILL' は parent.appendChild(child) の後に設定する必要があります — 前に設定すると例外が発生します。

  • ゴーストモード — すべてのバインディング操作の後に、ノードとそのすべての子に対して再帰的に setExplicitVariableModeForCollection を常に呼び出してください。これを省略すると、変数が未解決として表示されます。

  • バリアント数の上限 — コンポーネントセットあたり Size × State > 30 バリアントになる場合は、作成する前にユーザーに確認してください。サブコンポーネントへの分割を検討してください。

  • フォーカスリングの色の競合 — スキルはフォーカスリングの色について判断を下しません。コントラクトの color.focus.* トークンを読み取り、そこで定義されている Semantic 変数をすべてのバリアントに使用してください。focus/default がバリアントの塗りと同じ色である場合は、Generation Notes フレームでこれを指摘し、ユーザーに focus/onBrand Semantic トークンを定義することを提案してください。スキル独自の判断で neutral/0 やその他の色に置き換えないでください。

  • fullWidth と iconOnly はレイアウトを自動的に制御できません — Figma Plugin API の componentPropertyReferences は visible、characters、mainComponent のみをサポートしています。boolean を layoutSizingHorizontal にリンクしたり、アイコンのみとフルのレイアウトを切り替えたりすることはサポートしていません。これらのプロパティは spec/Code Connect の目的で定義されています。この制限を利用者向けに文書化してください — レイアウトの変更には手動でのバリアント作成か、後続のプラグインが必要です。

  • Figma プラグインサンドボックス — atob は undefined — プラグインのランタイムにはネイティブの base64 デコードがありません。プラグインスクリプトで atob や btoa を使用しないでください。スクリプトが 20k 文字の制限を超えて分割する必要がある場合は、base64 のポリフィルを使用するか、ロジックを複数の連続した use_figma 呼び出しに分割してください。

  • 回転値は常に度数であり、ラジアンではありません — Figma Plugin API の node.rotation プロパティは度数を受け付けます。常にコントラクトから度の値をそのまま渡してください(例: -90)。絶対にラジアン(-Math.PI/2)に変換しないでください。ラジアンを渡すと、Figma の UI では -1.57° のような値が表示され、視覚的な結果は正しくても見た目がおかしくなります。コントラクトの expandedRotation と defaultRotation フィールドは常に度数です。

  • Figma プラグインサンドボックス — eval はブロックされています — 動的なコード実行が必要な場合は、回避策として new Function(code)() を使用してください。これが Figma 環境で分割されたプラグインスクリプトを組み立てて実行するための唯一の信頼できるパターンです。

  • アイコンスロットの可視性 — アイコンのプレースホルダーフレームはデフォルトで非表示(visible: false)にし、componentPropertyReferences を介してタイプ visible の BOOLEAN コンポーネントプロパティ(iconStart)に紐付ける必要があります。アイコンスロットを常に可視のままにしないでください — アイコンを使用しないすべてのバリアントで空のボックスとして表示されます。

コメント