はじめに
Figma の MCP Server を Claude Code に接続すると、チャットだけで Figma にデザインを書き出し、そのままコード修正まで一気通貫できる。
今回、個人開発の NBA ニュースサイト(Kotlin Compose for Web)を、この方法で2026年風にリデザインした。本記事では実装手順とハマったポイントを共有する。
📌 この記事で扱うこと:
- Figma MCP Server (
use_figma) の使い方と制約 - Compose for Web の StyleSheet DSL でダークモード・Glassmorphism を実装する方法
-
<select>→ Pill タブへの移行パターン
環境
| 項目 | バージョン |
|---|---|
| Kotlin | 1.9.22 |
| Compose for Web | 1.5.12 |
| Claude Code | Opus 4.6 |
| Figma MCP Server | 公式プラグイン |
全体の流れ
1. Claude Code が Compose for Web のソースを読む
2. use_figma で Figma 上に現在のUIを再現
3. Figma 上で2026リデザイン版を作成
4. デザインをもとに StyleSheet DSL を書き換え
実装
ダークモードの適用
Compose for Web では StyleSheet オブジェクトの init ブロックに CSS を書く。ダークモード化は body と各コンポーネントの色を差し替える。
object AppStylesheet : StyleSheet() {
init {
"body" style {
backgroundColor(Color("#0f172a")) // slate-900
color(Color("#f1f5f9")) // slate-100
}
".app-header" style {
// ベタ塗り → グラデーション
property("background",
"linear-gradient(135deg, #1e40af 0%, #4f46e5 50%, #8b5cf6 100%)")
}
}
}
backgroundColor() は Compose for Web の型安全な API だが、linear-gradient のような複合値は property("background", "...") で直書きする必要がある。
Glassmorphism カード
".news-card" style {
backgroundColor(rgba(30, 41, 59, 0.6))
borderRadius(20.px)
property("border", "1px solid rgba(255,255,255,0.08)")
property("backdrop-filter", "blur(16px)")
property("box-shadow", "0 4px 24px rgba(0,0,0,0.25)")
property("transition", "transform 0.2s ease, box-shadow 0.2s ease")
}
".news-card:hover" style {
property("transform", "translateY(-2px)")
property("box-shadow", "0 8px 32px rgba(0,0,0,0.35)")
}
rgba() 関数は Compose for Web に組み込みで用意されている。backdrop-filter は property() で書く。
<select> → Pill タブへの置き換え
カテゴリフィルターを <select> から <button> ベースの Pill タブに変更した。
Before(ドロップダウン):
Select(attrs = {
classes("category-select")
onChange { event ->
val value = event.target.value
onCategorySelected(if (value.isEmpty()) null else value)
}
}) {
categories.forEach { (value, label) ->
Option(value = value ?: "", attrs = {
if (selectedCategory == value) selected()
}) { Text(label) }
}
}
After(Pill タブ):
Div(attrs = { classes("category-filter") }) {
categories.forEach { (value, label) ->
Button(attrs = {
classes("category-pill")
if (selectedCategory == value) {
classes("category-pill-active")
}
onClick { onCategorySelected(value) }
}) {
Text(label)
}
}
}
Select / Option / selected() のインポートが不要になり、コードがシンプルになった。CSS 側はアクティブ状態にグラデーションを適用:
".category-pill-active" style {
property("background", "linear-gradient(135deg, #3b82f6, #8b5cf6)")
color(Color.white)
fontWeight(600)
opacity(1)
}
Bento Grid
先頭のニュースを大きく見せる Bento Grid は、CSS Grid の :first-child 疑似セレクタで実現:
".news-grid" style {
display(DisplayStyle.Grid)
property("grid-template-columns", "repeat(3, 1fr)")
gap(1.25.em)
}
// 先頭カードを2列分に拡大
".news-grid > *:first-child" style {
property("grid-column", "span 2")
}
// モバイルではフォールバック
media("(max-width: 600px)") {
".news-grid > *:first-child" style {
property("grid-column", "span 1")
}
}
Compose for Web の media() 関数でレスポンシブ対応もそのまま書ける。
ハマったポイント
1. Figma MCP: fills の color に alpha を指定できない
// ❌ エラーになる
node.fills = [{ type: 'SOLID', color: { r: 1, g: 1, b: 1, a: 0.9 } }]
Figma Plugin API の fills の color は {r, g, b} のみ。透過は opacity プロパティで設定する:
// ✅ 正しい
node.fills = [{ type: 'SOLID', color: { r: 1, g: 1, b: 1 } }]
node.opacity = 0.9
2. Figma MCP: layoutSizingHorizontal = "FILL" の設定タイミング
// ❌ appendChild の前に設定するとエラー
child.layoutSizingHorizontal = "FILL"
parent.appendChild(child)
// ✅ appendChild の後に設定する
parent.appendChild(child)
child.layoutSizingHorizontal = "FILL"
Auto Layout のサイジングモードは、親フレームに追加された後でないと設定できない。use_figma で一番踏みやすいバグ。
3. Figma MCP: 1回のスクリプトでやりすぎない
ヘッダー + フィルター + カード6枚 + フッターを1回の use_figma で書こうとすると、スクリプトが長くなりすぎて失敗する。
セクション単位で分割して、各回で get_screenshot を挟んで確認するのがベスト:
use_figma → ラッパー作成 → get_screenshot で確認
use_figma → ヘッダー作成 → get_screenshot で確認
use_figma → フィルター作成 → get_screenshot で確認
use_figma → カード Row 1 → get_screenshot で確認
use_figma → カード Row 2 → get_screenshot で確認
use_figma → フッター作成 → get_screenshot で確認
4. Compose for Web: property() に頼る場面が多い
型安全な API が用意されているプロパティ(backgroundColor, borderRadius, padding 等)はそのまま使えるが、以下は property() が必要:
| プロパティ | 書き方 |
|---|---|
linear-gradient |
property("background", "linear-gradient(...)") |
backdrop-filter |
property("backdrop-filter", "blur(16px)") |
box-shadow |
property("box-shadow", "0 4px 24px ...") |
transform |
property("transform", "translateY(-2px)") |
grid-template-columns |
property("grid-template-columns", "repeat(3, 1fr)") |
grid-column |
property("grid-column", "span 2") |
transition |
property("transition", "all 0.2s ease") |
CSS Grid 系はほぼ全て property() 経由になる。
まとめ
- Figma MCP × Claude Code で デザイン → プロトタイプ → コード修正 を1セッションで完結できた
- Compose for Web の StyleSheet DSL は
property()を活用すればモダンCSS(Glassmorphism, Grid, グラデーション等)を問題なく実装できる - Figma MCP は
use_figmaのスクリプト分割とfillsの alpha 制約に注意
Compose for Web の日本語情報はまだ少ないので、同じ技術スタックで開発している方の参考になれば。
🏀 NBA ISO FLOW: https://www.nba-iso-flow.com/
NBAの最新トレード・FA・ニュースを日本語でリアルタイム配信中。Kotlin Compose for Web + Rust(Axum)で構築した個人開発プロジェクト。