Figma Code Connectをライブラリ無しのHTML/CSS実装で使う
X-tech推進本部 倉原3月に公開したAIフレンドリーなFigmaデータとは?(第二弾)では、Figma MCP Serverのget_design_contextで取得したコードをAIに渡し、Figmaデータの作り方によって実装結果がどう変わるかを検証しました。Figmaでコンポーネント化しておくと、役割に紐づいた再利用しやすいクラスでコードが書かれる、というのがその結論の1つでした。
今回は、Figmaのコンポーネントとソースコードで実装済みのコンポーネントを紐づけるCode Connectを取り上げます。
Code Connectで実装済みのコンポーネントと紐づけておくと、get_design_contextの出力では、デザインから自動生成したコードの代わりに、そのコンポーネントを呼び出すコード(例:<Button variant="primary" />とimport文)が返ってきます。
Code Connectは通常、Reactなどのライブラリで実装したコンポーネントのコードと紐づけて使うものですが、本記事では、紐づけ先をHTML/CSSで作成したコンポーネント一覧に置き換えられるかを検証した結果を紹介します。
Code Connectが解決すること
get_design_contextは、デフォルトではReact + Tailwindのコードを返します。
Code Connectで紐づけておくと、該当するインスタンスが<CodeConnectSnippet>という要素に置き換わり、その中に実装したコードが入ります。AIはこれを手がかりに、実装済みのコードのコンポーネントを呼び出すコードを書けるようになります。
HTML/CSS案件では何に紐づけるか
今回取り組むのは、紐づけ先をデフォルト設定のReactコンポーネントではなく、ライブラリやフレームワークを利用していないHTML/CSSで作成したコンポーネントにすることです。
例えば、ボタンを例にとるとHTMLのコードは下記のようになります。
<a class="m-button" href="...">お問い合わせ</a>
<a class="m-button m-button--emphasis" href="...">お問い合わせ</a>
Figmaで作ったbuttonコンポーネントが、Reactのコードではなく、上記のようなHTMLのコードとして出力されることを目指します。
検証の構成
検証用に、簡易なコンポーネント一覧とFigmaデザインを用意しました。ボタンのコンポーネントはsrc/pages/components/button.ejsとして用意しました(ビルドすると普通のHTMLになります)。Figma側のコンポーネント名は、HTML/CSSで実装したボタンのクラス名と同じにしています。
| Figmaコンポーネント | プロパティ |
|---|---|
| m-button | Label、Style(Default / Emphasis / Conversion)、State(Default / Disabled)、ShowIcon、Icon |
ボタンを含むサンプルのデザインも作り、get_design_contextでサンプル全体を取得した時に、ボタンのコードはどのように出力されるのかを分かるようにしました。
第1段階:send_code_connect_mappingsでコンポーネントを紐づける
Figma MCP Serverのsend_code_connect_mappingsツールを使って、m-buttonを登録します。
手順は次のとおりです。
1. Figmaでライブラリを公開する
登録の対象になるのは、公開済みのコンポーネントだけです。Figmaでファイルを開き、左メニューのアセット → Libraries → 公開でコンポーネントを公開します。

2. get_code_connect_suggestionsで紐づけるコンポーネントを確認する
Figma MCP Serverのget_code_connect_suggestionsに、FigmaのURL(https://www.figma.com/design/XXXX/?node-id=6-13のような、フレームを選択したリンク)を渡すと、そのフレーム内で使われていて、まだ紐づいていないコンポーネントの一覧が返ります。ここでm-buttonが対象に含まれていることを確認します。
3. send_code_connect_mappingsで登録する
Figma MCP Serverのsend_code_connect_mappingsには、次のようにJSON形式でFigmaのファイルとノード、紐づけの一覧を一緒に渡します。
{
"fileKey": "XXXX",
"nodeId": "6:13",
"clientFrameworks": "web components",
"clientLanguages": "html,css,javascript",
"mappings": [
{
"nodeId": "3:39",
"componentName": "m-button",
"source": "src/pages/components/button.ejs#mml-m-button",
"label": "Web Components"
}
]
}
mappingsの各項目の意味は次のとおりです。
| 項目 | 内容 |
|---|---|
nodeId |
Figmaのコンポーネントのノード ID |
componentName |
コード側のコンポーネント名。ここではモジュールのクラス名 |
source |
コンポーネントのソースコードが記載されたファイルのパス。ここではコンポーネント一覧のボタンのページ(button.ejs)と、ボタンの項目へのアンカー |
label |
どのフレームワーク向けの記録か。HTMLという選択肢は存在しないため、Web Componentsを使う |
実際には、AIエージェントに「このページのm-buttonを、このモジュールとWeb Componentsラベルで紐づけて」のような形で依頼し、エージェントが1〜3のツールを順に呼んでいます。人が行うのは、ライブラリの公開と、提案された紐づけの確認です。
4. 登録結果を確認する
get_design_contextにclientFrameworks: "web components"を渡してページのデザインデータを取得すると、ボタンの部分のコードは次のようになります(抜粋)。
<m-button showIcon={false} icon="3:2" label="事例を見る" style="Emphasis" state="Default" />
HTMLのように見えますが、これはFigmaのコンポーネント名をタグ名に、プロパティ(StyleがEmphasisなど)を属性にして並べただけのものです。目的の<a class="m-button m-button--emphasis">にするには、style="Emphasis"をm-button--emphasisというクラスに置き換える必要があります。
第1段階で登録したのは「Figmaのm-buttonは、コードのm-buttonと同じもの」という紐づけだけです。そのため返ってくるのも「どのコンポーネントの、どのプロパティがどの値か」までで、それをどのクラス名にするかまでは分かりません。この置き換えを推測でAIに任せると、m-button--EmphasisのようにCSSに存在しないクラス名を作ってしまうおそれがあります。
第2段階:Code Connect CLIで返すHTMLまで登録する
第1段階のままでは、<m-button>のようなタグをHTMLに置き換える作業が残ります。Figmaが公開しているコマンドラインツール、Code Connect CLI(@figma/code-connect)を使うと、紐づけに加えて「どんなHTMLを返すか」まで登録できるので、この置き換えが要らなくなります。
CLIでは、Figmaのコンポーネントごとに「どんなコードを返すか」を書いたファイルを登録できます(Code Connectではこれをテンプレートと呼びます)。今回はm-button用にsrc/figma/m-button.figma.tsを1つ作りました。このファイルはCLIでFigmaにアップロードされ、get_design_contextが呼ばれたときにFigma側で実行されます。
m-button.figma.tsの中身は次のとおりです。
// url=https://www.figma.com/design/XXXX/?node-id=3-39
// source=src/pages/components/button.ejs#mml-m-button
// component=m-button
import figma from 'figma'
const instance = figma.selectedInstance
const label = instance.getString('Label')
const modifier = instance.getEnum('Style', {
Default: '',
Emphasis: ' m-button--emphasis',
Conversion: ' m-button--conversion',
})
const disabled = instance.getEnum('State', { Default: false, Disabled: true })
export default {
example: figma.html`<a class="m-button${modifier}"${disabled ? '' : ' href="DUMMY_LINK"'}>${label}</a>`,
id: 'm-button',
metadata: { nestable: true },
}
上記コードについての説明は下記を参考にしてください。
| 箇所 | 内容 |
|---|---|
| 先頭のコメント | urlで紐づけるFigmaのコンポーネント(m-button、ノードID 3:39)を、sourceでコード側の場所を指定する。第1段階のsend_code_connect_mappingsに渡していたnodeIdやsourceと同じ情報 |
figma.selectedInstance |
コードを出力する対象のインスタンス(ページ上の個々のボタン)。import figma from 'figma'のfigmaはFigmaが実行時に用意するもので、自分で取得する必要はない |
getString / getEnum |
そのボタンのプロパティ値を取り出す。getEnumではFigmaの値ごとに、付けるクラス名を書く |
example |
返すHTML。figma.html`...`の中に、取り出した値を埋め込んだHTMLを書く |
get_design_contextを呼ぶと、ページ内のm-buttonのインスタンスごとにこのファイルが実行され、ボタンごとに違うHTMLが返ります。
Emphasisにはm-button--emphasisを付ける、というように、値とクラス名の対応を書くので、CSSに存在しないクラス名が出力されることはありません。
CLIがこのファイルを見つけられるように、設定ファイルfigma.config.jsonにテンプレートの置き場所とラベル・言語を書きます。
{
"codeConnect": {
"include": ["src/figma/**/*.figma.ts"],
"label": "Web Components",
"language": "html"
}
}
あとはnpx figma connect publishを実行すると、includeに当てはまるm-button.figma.tsがFigmaに登録されます。
登録後、同じページをget_design_contextで取り直すと、ボタンの<CodeConnectSnippet>の中身がモジュールのHTMLになりました。
<a class="m-button m-button--emphasis" href="DUMMY_LINK">事例を見る</a>
<a class="m-button m-button--conversion" href="DUMMY_LINK">フォームで問い合わせる</a>
<a class="m-button">電話で問い合わせる(受付終了)</a>
非活性のボタンはhrefのないa要素になっています。紐づけていないコンポーネントやレイアウトの枠は、これまでどおりTailwindのコードで返ってきます。
おわりに
1月に公開したAIフレンドリーなFigmaデータとは?ではコンポーネント化やプロパティ設計について書きました。Code Connectはその後の「デザインのコンポーネントと実装のコンポーネントをつなげる」ための仕組みです。
テンプレートまで登録すれば、Figma URLを渡すだけで、get_design_contextからコンポーネントのHTMLがそのまま返ってきます。AIに「見た目を再現させる」のではなく「既存のコンポーネントを使わせる」ための土台として、フレームワークを採用していないHTML/CSS案件でも使えるコードが返ってきます。