• #Claude Code
  • #Claude Web
  • #SVG
  • #Vue
  • #状態遷移図
  • #デザインシステム
開発未分類メモ

Claude CodeとClaude Webを組み合わせてSVG状態遷移図を作った話

結論

Claude Codeでフロントエンド開発をしていると、SVGで図を作りたい場面がある。複雑なSVGの生成はClaude Codeが苦手なので、Claude Web(claude.ai)で図の構造を作り、Claude Codeに渡して実装するという分業が効果的だった。

最終的にできたのは、ボタン操作で状態が変わり、対応するカードがハイライトされるインタラクティブな状態遷移図。

最終的なV3実装

背景: なぜ状態遷移図が必要だったか

Tax Assistantというプロジェクトで、勘定科目選択UIの色ルールをドキュメント化したかった。

クレジットカード明細の画面で「一致」「候補」「不一致」などのステータスを色で区別している。この色の使い分けルールをDesign Systemページにまとめていた。

修正前のクレカ明細画面

勘定科目選択の色ルールは少し複雑で、以下の5状態がある。

状態確定値選択値説明
未確定なしAI提案と同じAI提案のまま
未確定(変更あり)オレンジなしAI提案と異なるAI提案から変更
編集中あり確定値と同じ確定後の再編集
編集中(変更あり)オレンジあり確定値と異なる確定値から変更
確定済みあり-保存完了

「未確定(変更あり)」と「編集中(変更あり)」が同じオレンジなのは、どちらも「現在の選択が基準値と異なる」という状態を表すため。色を統一することで、ユーザーは「オレンジ = 変更あり」と直感的に理解できる。

テキストだけでは伝わりにくいので、状態遷移図を作ることにした。

試行1: イラストレーターでラフを作成

まず自分でイラストレーターで簡単なラフを作った。矢印は省略して、カードの配置と色だけ示したもの。

イラストレーターで作成したラフ

これをClaude Codeに渡して「この図をSVGで実装して」と依頼した。

結果は微妙だった。複雑なSVGの座標計算やパス描画はClaude Codeの苦手分野で、カードの配置がずれたり、矢印がおかしな方向を向いたりした。

試行2: Claude Webで図を生成

Claude Code単体では難しいと判断し、Claude Web(claude.ai)を使うことにした。Claude Webはアーティファクト機能でSVGやReactコンポーネントを生成できる。

イラストレーターのラフをClaude Webに渡して「この状態遷移図をSVGで作って」と依頼。

Claude Webで生成した初期バージョン

かなり良い図が生成された。矢印の配置も適切で、各状態の色分けも正しい。

試行3: Claude Codeでインタラクティブ化

Claude Webで生成したSVGをClaude Codeに渡し、Vueコンポーネントとして実装してもらった。

目標は以下の機能。

  • ボタンで状態を操作(保存、編集、科目変更)
  • 現在の状態に対応するカードがハイライト
  • 勘定科目を選択すると色が変わる

インタラクティブデモの初期版

基本的な動作はできたが、問題が発生した。

問題: ループのハイライトが正しくない

確定済み→編集→変更→保存というループを表現したかった。しかし「編集中(変更あり)」から保存したとき、上の「確定済み」カードがハイライトされてしまう。

ループの問題

原因は、ハイライト判定がcurrentStateのみで行われていたこと。状態がconfirmedになると、どの経路で確定したかの情報が失われ、常に同じカードがハイライトされていた。

本来は下の「確定済み」カード(ループの終点)がハイライトされるべき。

解決策1: 8カードに分割(V2)

最初の解決策として、「確定済み」カードを2つに分けた。

  • 上の確定済み: 未確定から直接保存したとき用
  • 下の確定済み: 編集中(変更あり)から保存したとき用

V2: 8カード版

これで動作は正しくなったが、カードが8枚になって図が複雑になった。同じ「確定済み」状態なのにカードが2つあるのは冗長に感じる。

解決策2: 動的テキスト+ループ(V3)

最終的な解決策として、カードの内容を動的に変更するV3を採用。

ポイント:

  • カードは5枚に削減
  • 「編集中」カードの説明文が動的に変わる(例: 「確定値(接待交際費)と同じ = 青」)
  • 保存時の経路を記録し、適切なカードをハイライト

状態管理

// 状態の型定義
type State = 'unconfirmed' | 'editing' | 'editing-changed' | 'confirmed'

const currentState = ref<State>('unconfirmed')
const selectedAccount = ref('会議費')      // 現在選択中の科目
const confirmedAccount = ref<string | null>(null)  // 確定済みの科目
const savedFromEditingChanged = ref(false) // 経路記録用フラグ

状態遷移関数

// 保存: 経路を記録して確定状態へ
function saveAccount() {
  savedFromEditingChanged.value = currentState.value === 'editing-changed'
  confirmedAccount.value = selectedAccount.value
  currentState.value = 'confirmed'
}

// 編集: 確定済みから編集状態へ
function startEditing() {
  currentState.value = 'editing'
}

// 科目変更: 状態に応じて変更あり状態へ
function selectAccount(account: string) {
  selectedAccount.value = account
  if (currentState.value === 'unconfirmed' && account !== aiSuggestedAccount) {
    // 未確定でAI提案と異なる → 未確定(変更あり)は色だけ変わる
  } else if (currentState.value === 'editing' && account !== confirmedAccount.value) {
    currentState.value = 'editing-changed'
  } else if (currentState.value === 'editing-changed' && account === confirmedAccount.value) {
    currentState.value = 'editing'
  }
}

ハイライト判定

// カードのハイライト判定
function isCardHighlighted(cardType: string): boolean {
  return currentState.value === cardType
}

SVG側では、savedFromEditingChangedフラグを使ってどちらの「確定済み」カードをハイライトするか決定。

<!-- 上の確定済み: 未確定から直接保存 -->
<rect :filter="isCardHighlighted('confirmed') && !savedFromEditingChanged
  ? 'url(#card-highlight)' : ''" />

<!-- 下の確定済み: ループ経由で保存 -->
<rect :filter="isCardHighlighted('confirmed') && savedFromEditingChanged
  ? 'url(#card-highlight)' : ''" />

完成した状態遷移図

最終的なV3実装では、以下の操作ができる。

  1. 勘定科目を選択 → 「未確定(変更あり)」
  2. 保存 → 「確定済み」(上のカードがハイライト)
  3. 編集 → 「編集中」(動的テキストが更新)
  4. 別の科目を選択 → 「編集中(変更あり)」
  5. 保存 → 「確定済み」(下のカードがハイライト)

最終的なV3実装

Claude CodeとClaude Webの使い分け

今回の経験から、以下の使い分けが有効だと感じた。

タスク適したツール
複雑なSVG図の生成Claude Web
コードベースへの統合Claude Code
インタラクティブ機能の実装Claude Code
既存ファイルの編集Claude Code

Claude Webはアーティファクトで視覚的なフィードバックを得ながら図を調整できる。一方Claude Codeは、プロジェクトのコンテキストを理解し、既存コードと整合性のある実装ができる。

両者を組み合わせることで、どちらか単体では難しいタスクも効率的に進められた。

まとめ

  • 状態遷移図のような複雑なSVGは、Claude Webで生成してClaude Codeに渡すのが効果的
  • ループを含む状態遷移は、経路を記録してハイライト先を切り替える
  • 動的コンテンツを使えば、カード数を減らしつつ正確な状態遷移を表現できる