デジタルエンジニアリング部 Eビジネスエンジニアリング課の小枝です。
前回は、Figma Makeにプロンプトからデザインとプロトタイプを生成してもらいました。
今回はそれをもとに、Claude Codeでコードの品質を上げてもらいます。
出力されたコードを開いて、使われている技術の確認をします。
普段はデザインがメインの業務なので、Reactには触れてきませんでした。
今回、特に指定していなかったのに、Reactとshadcn/uiを採用してくるのは便利になったというか……。AIの進化ってすごい。
Figma Make上での動作は確認済みですが、Claude Codeに渡す前にローカルでも起動してみます。
README.mdが生成されているので、手順に沿って起動します。
ちゃんと生成されているのも便利。
Figma Make上のデザインそのままの画面が表示されました。
動作は概ね問題ないです。 ただ、hoverやボタンの大きさなど調整したいところがいくつかあるので、修正点をClaude Codeに伝えて対応してもらいます。
まず、見た目やマイクロインタラクション等の修正から進めます。
複数の修正をまとめて頼むと意図しない変更が入りやすいそうなので、1回に1つの修正を加えます。
実際にこんな指示を出しました(一例)。
配色選択のボタンにhoverのアニメーションの設定と、カーソルをポインターにしてください。アニメーションは0.3秒、easeにしてください。
アニメーション自体は動作しましたが、hover時の装飾を明確に指定しなかったので透過度を変更するなどの処理になり、修正するために複数のやり取りが発生しました……。
最終的には選択時と同じ装飾にしてくださいと指定してコントロールできました。あいまいな指示が良くなかったです。
カラーピッカーとシャッフルボタンも同じようにしてください。また、カラーピッカーのアウトラインも非表示にしてください。
この指示の後、アウトラインが非表示にならなかったのと、押せる感が薄くなったので、カラーピッカーのアイコンについても追加してもらいました。
当初はアクセントカラーが3色で配色の種別にトライアドを用意してもらいましたが、途中で4色になったので名前と挙動の調整をお願いします。
Figma Makeの時に4色にしてもらいましたが、記述や計算式に関しては特に指定していなかった部分です。
ちゃんと直してもらえました。
いろいろ修正も入れましたし、Claude Codeにコードレビューをしてもらいました。
コードを見た上でのアドバイスです。
現状の App.tsx は大きく3つの役割が混在しています:
色の計算ロジック(hexToRgb、generatePalette など、1〜173行)
型定義(ColorScheme、ColorPalette)
画面の描画(App コンポーネント本体)
Reactを知らなくても取り組みやすい順番でいうと:
ステップ1:型定義を切り出す(一番簡単)
src/types.ts を作って ColorScheme と ColorPalette を移すだけ。Reactの知識ゼロでできます。
ステップ2:色の計算関数を切り出す(次に簡単)
src/utils/color.ts を作って hexToRgb から generatePalette までを移す。これも純粋な関数なのでReactと無関係です。
ステップ3:コンポーネント分割(Reactの理解が必要)
左パネル・右パネル・下段を別ファイルにする。これは「propsで値を渡す」というReactの概念が必要になるので、1・2が終わってから検討するのが良いと思います。
ひとまずステップ1と2をやってもらうことにしました。
必要なファイルの作成とApp.tsxの整理をしてもらいましたが、何をしたのかの解説もお願いしました。
「何をしたか」を図で説明します。
Before(変更前)
App.tsx(1ファイルに全部)
├── type ColorScheme = ... ← 型定義
├── interface ColorPalette = ... ← 型定義
├── function hexToRgb() ... ← 色計算
├── function rgbToHsl() ... ← 色計算
├── function getContrastRatio() ← 色計算
├── function generatePalette() ← 色計算
└── function App() { ... } ← 画面描画
After(変更後)
types.ts → 型定義だけ
utils/color.ts → 色計算の関数だけ
App.tsx → 画面描画だけ(上2つをimportして使う)
なぜ分けるのか、一言でいうと「1つのファイルには1つの役割」というルールに従うためです。
料理で例えると、レシピ(型定義)・調理道具の使い方(色計算)・盛り付け(画面描画)が1枚の紙に書いてあったのを、3枚に分けたイメージです。どこに何が書いてあるか探しやすくなります。
import というのは「他のファイルから持ってくる」命令です。変更後の App.tsx の先頭にある:
import { generatePalette, getReadableColor } from '../utils/color';
これは「utils/color.ts の中にある generatePalette と getReadableColor を使わせてもらう」という意味です。
想定より分かりやすい説明をしてくれて良かったです。判断しやすい。
ステップ3に関しては計画を立てた上で進めてくれました。
以下はClaude Codeの出力をそのまま引用しています。
ステップ3(コンポーネント分割)の内容を確認してから計画を立てます。
Used tool: Agent
Read src/app/App.tsx
計画を書きます。
Here is Claude's plan:
# Context
現在のApp.tsxは型定義と色計算関数を分割済み。次のステップとして、UIコンポーネントを分割し、可読性と保守性を向上させる。
# Plan
App.tsxを3つの子コンポーネントに分割:
## 1. CSSOutputPanel.tsx(最初に実装)
- 役割: 下段のCSS出力エリア
- 必要なprops: `palette: ColorPalette`
- ローカルstate: `copied`(コピー完了フラグ)
## 2. ColorSwatchPanel.tsx
- 役割: 右パネルの3色スウォッチ表示
- 必要なprops: `colors: string[]`
- stateなし(純粋な表示コンポーネント)
## 3. KeyColorPanel.tsx
- 役割: 左パネルのキーカラー選択と操作
- 必要なprops: `keyColor`, `scheme`, `onKeyColorChange`, `onSchemeChange`, `onRandomColor`
- ローカルstate: `hoveredScheme`, `hoveredColorPicker`, `hoveredShuffle`
## 4. App.tsx(親)
- state保持: `keyColor`, `scheme`, `palette`
- useEffect: `keyColor`と`scheme`変更を監視
- 子コンポーネントをレイアウトで配置
## ファイル構造
src/
├── types.ts
├── utils/color.ts
├── app/
│ ├── App.tsx(整理済み)
│ └── components/
│ ├── KeyColorPanel.tsx(新規)
│ ├── ColorSwatchPanel.tsx(新規)
│ └── CSSOutputPanel.tsx(新規)
# Verification
- `npm run dev` で開発サーバー起動
- 各コンポーネントが正しく表示されることを確認
- ボタン操作・色変更・コピー機能がすべて動作することを確認
- コンソールにエラーがないこと確認
計画が既に承認済みなので、実装を進めます。
3つのコンポーネントを順番に作ります。最初に `CSSOutputPanel.tsx`:
次に `ColorSwatchPanel.tsx`:
次に `KeyColorPanel.tsx`:
最後に `App.tsx` を新しい子コンポーネントに置き換えます:
Read src/app/App.tsx
完了です。最終的なファイル構造:
src/
├── types.ts # 型定義
├── utils/color.ts # 色計算関数
└── app/
├── App.tsx # 親コンポーネント(25行)
└── components/
├── KeyColorPanel.tsx # 左パネル
├── ColorSwatchPanel.tsx # 右パネル
└── CSSOutputPanel.tsx # 下段
`App.tsx` が元の 236行から 41行に削減されました。各コンポーネントが責任を持つので、今後の変更が簡単になります。
変更を行いました。
各コンポーネントに機能が分割され、責任の所在が明確になりました。
ここまで対応してもらえてすごく助かります。
コードの修正が終わったので、Claude Codeに自己レビューをお願いしました。
ここまでしてくれるならきっと良いレビューも上がってくるだろうと。
思っていた以上にしっかりしたレビューを上げてくれました。
今回はユーザビリティを重視しているので、まずP2まで対応してもらうことにしました。
P3は規模が小さかったのでついでにお願いしました。P0から順番に進めます。
バグ修正・エラーハンドリングの追加
アクセシビリティ・操作性の改善
コントラスト計算・CSS生成ロジックの重複解消
マジックナンバーの定数化・ホバー管理の共通化
順番に指示を出して修正してもらい、最後に対応内容をまとめて報告してもらいました。
数分で対応してこういった報告をしてもらえるの、良いです。
ともあれ、P0~3の修正点すべてを対応してもらったので、改めてレビューをお願いしました。
| 内容 | ファイル |
|---|---|
generatePalette() のswitch文が長く、同じパターンが4回繰り返されている |
src/utils/color.ts |
| カラーピッカーとシャッフルボタンのスタイルロジックが重複している | src/app/components/KeyColorPanel.tsx |
| 内容 | ファイル |
|---|---|
schemeLabels がコンポーネント内にあり、他から再利用できない |
src/app/components/KeyColorPanel.tsx |
handleCopy にCSS生成・クリップボード操作・状態管理が混在している |
src/app/components/CSSOutputPanel.tsx |
buildColorEntries() が同一レンダリング内で2回呼ばれている |
src/app/components/CSSOutputPanel.tsx |
ハードコードされた色値(#1e1e1e など)が散在している |
全体 |
useHoverState の戻り値の hoverProps という名前が何をspreadするか分かりにくい |
src/app/hooks/useHoverState.ts |
| 内容 | ファイル |
|---|---|
getLuminance の計算式(WCAG基準)にコメントがない |
src/utils/color.ts |
16777216 が何の数字か分からない |
src/app/App.tsx |
setTimeout のクリーンアップがなくメモリリークの可能性 |
src/app/components/CSSOutputPanel.tsx |
初回レビューで取り残した項目がわらわらと出てきました。
漏れ抜け方がロボット掃除機みたいな印象がありますね。 でもまあせっかくなので、すべて対応してもらうことにします。
高優先度から順番に進めてもらいます。
| # | 優先度 | ファイル | 変更内容 |
|---|---|---|---|
| ① | 高 | color.ts |
getContrastInfo() を追加、getContrastRatio の複数回呼び出しを1回にまとめ |
| ② | 高 | KeyColorPanel.tsx |
ICON_CIRCLE_CLASS 定数・getIconCircleStyle() 関数を抽出、カラーピッカーとシャッフルボタンの重複スタイルを統合 |
| ③ | 高 | hooks/useHoverState.ts |
useHoverState カスタムフック導入、onMouseEnter/Leave の定型パターンを再利用可能に |
| ④ | 中 | constants/design.ts |
SCHEME_LABELS を移動、KeyColorPanel のラベルオブジェクトを定数化 |
| ⑤ | 中 | CSSOutputPanel.tsx |
buildCSSText() 抽出、copyToClipboard() 抽出、colorEntries を一度だけ計算、handleCopy を async/try-catch に変更 |
| ⑥ | 中 | constants/theme.ts(新規) |
THEME 定数を作成、CSS出力パネルの配色をファイルに集約 |
| ⑦ | 低 | color.ts |
getLuminance にWCAGコメント追加、generateRandomHex() を抽出 |
| ⑧ | 低 | CSSOutputPanel.tsx |
setTimeout クリーンアップ、useRef + useEffect でタイマー漏れを防止 |
こちらも数分で対応が終わり、報告までしてもらいました。 便利すぎる。
その後も対応→レビュー→対応のサイクルを繰り返しました。
回を重ねるごとに指摘が細かくなっていきます。
重要度高めのものから検知しやすいのかもしれないです。
3回目は初期カラーの二重定義(定数化で解消)や、関数間のロジック重複、変数名の統一など6件。
4回目は破壊的代入の修正漏れや不要な再レンダリング(useMemoで解消)など5件。
5回目は低優先度2件のみで、ほぼスタイルの統一の話でした。
5回目の修正後のチェックでようやく指摘がなくなり、問題のないコードになりました。
思ったより回数がかかりましたね……。
途中トークンの上限が見えてきたりしたので、レビューの範囲や回数はもう少し工夫ができたのかもしれません……。
アプリが完成しました!主な機能は4つ!
今回のカラーピッカーアプリでは、コントラスト比チェック機能を搭載しています。
Figma Makeへのプロンプトの時点で明確に指定して作ってもらいました。
コントラスト比はWCAGの基準に沿って計算されていて、式は (明るい色のL + 0.05) / (暗い色のL + 0.05) です。
AA基準が4.5:1、AAA基準が7:1なので、これを自動で判定して分かりやすくしています。
Claude Codeのレビューでは getLuminance にWCAGの計算式コメントを追記する提案もありました。
可読性に気を配ってくれるのも良い働きです。
今回使ってみて、2つのツールの役割分担がはっきりしていると感じました。
Figma Make は「速く動くものを作る」ツール。UIのビジュアルから一気にコードまで出してくれるスピード感は、体験としてかなり面白かったです。優秀なアシスタントが付いてくれた感じですね。 一方、Claude Codeは「品質・保守性を上げる」ツール。レビューを繰り返すことで、とりあえず動くコードが整理されきれいになりました。
最初から完璧を目指すより、まずFigma Makeで形にしてClaude Codeで品質を上げる、という流れが自分には合っていそうです。
Figma Makeの時点でここまで動くものができるとは正直思っていませんでした。プロトタイプを作るスピード感がすごい。
ただ、思いつくまま生成させるとコントロールが難しくなるので、事前に伝えておく要件はある程度整理しておいたほうが良さそうです。
あとはAIに寄りかかりすぎないことですかね。AIが出したものをそのまま使うのではなく、自分でちゃんと理解・確認しながら使う姿勢は大事だと思います。
デザイナー目線で使ってみると、コードの説明が丁寧で「なぜこうすべきか」まで教えてもらえるのが良かったです。
Figma Makeは「デザインを出してくれる」ツールですが、Claude Codeは「一緒に考えてくれる」感覚に近いかもしれないです。
気になった点としては、トークンの上限があるのでやり取りが長引くと会話を切り直す必要があることですかね。
レビュー範囲の区切り方などをもう少し工夫できたかなと思います。