開発eurekapu-nuxt4

画面を見て違和感を拾うところから始まった

簿記3級の練習問題ページ /quiz/practice を触っていて、目が止まった。仕訳を解答すると、対応する勘定科目に「飛んでくるピル」が着弾して、BS/PL の数字が更新される。しかし前の問題で青くハイライトされた行が、次問の着弾が始まる手前で消えずに残っている。仕入と買掛金が新しく光るはずの瞬間に、1つ前の現金や売上の行も同時に青いままで、画面が「どこを見るべきか」を伝えてこない。

電卓も検算もしていない。画面のチカチカに違和感を覚えただけで、Claude Code に「アニメーションが着弾する前に1つ前の問題のハイライトが消えていない」と投げた。

原因: pendingApply 中も changed フラグが再計算で残っていた

Claude Code が cumulativeImpact の評価タイミングを追って、原因を特定した。

  • 解答 → 着弾 → BS/PL 反映までは pendingApply.value が立っている
  • その間も cumulativeImpact は再計算が走り、前問の changed フラグを残したまま返ってくる
  • 結果、新しい行が光る前のフレームで、古い行も光ったままになる

修正方針はシンプルで、「pendingApply.value が立っている間は clearChanged を適用する」だけ。前問のハイライトを次問の着弾前にリセットすれば、画面の注目点が1箇所に収束する。

ついでに着弾色の指定も直した。マイナスを赤で表現していたところに、プラスは緑を割り当てた。感情科目のプラス/マイナスを背景色で表現する形に揃えて、貸借どちらに振れているかが色だけで読めるようにした。

アニメが速すぎる/しつこいというフィードバック

修正してプレビューを見ていたら、今度は別の不満が湧いた。着弾アニメが速すぎて、しかも全問必ず走る。10問連続で解くと、ピルが10回飛んで10回着弾する。集中して解いている時にうるさい。

「ON/OFF トグルを足したい」と Claude Code に頼んだ。デザインは既に画面右上に置いてある「C/S トグル」(簿記の T勘定 ⇔ ストック表示の切替)と同じ作りで揃えた。トグルを切ると、解答時の着弾アニメが消えて、即時に数字が反映される。

ここでまずやりすぎた

試行錯誤: 全部止めようとしたら『カウントアップは残せ』と差し戻された

Claude Code に「アニメーション ON/OFF トグル」と頼んだら、practice.vue から FinancialStatementBS / FinancialStatementPL まで animationsEnabled プロップを通して、カウントアップ・ハイライト・delta popup・fly-pill を全部一括でスキップする形に組まれた。OFF にすれば全アニメが消えて、数字だけが瞬時に切り替わる。一見スッキリした。

しかしプレビューを触り直して気づいた。カウントアップが消えると「どこの数字が動いたか」が分からない。BS と PL は20行以上ある表で、目で追うには動きの手がかりが要る。delta popup(数字の上に「-2,000」が浮き出る演出)も、貸借バランスの動きを読むのに役立っていた。要するに、自分が削りたかったのは「ピルが画面を横切ってくる」演出だけで、表内の動きは残してほしかった。

差し戻した。

カウントアップのアニメーションは残してていいんですよ。BSとPLのその代わり、仕分けの飛んでくるアニメーションがあるじゃないですか、着弾するアニメーションがオンオフ切り替えられたらいいかなって感じです。カウントアップのアニメーションはどこが動いてるか見やすいんでハイライト含めてそれは入れててほしいんですけどね。あと、数字から浮き出てくるようなアニメーションもあったじゃないですか、そこは置いといていいですよ、そのまま。

Claude Code が practice.vue 側のプロップバインディングを外し、トグルの作用範囲を fly-pill のみに絞り直した。

  • カウントアップ: 残す(数字が動いた場所を目で追える)
  • ハイライト: 残す(注目すべき行が分かる)
  • delta popup(数字から浮き出る -2,000 等): 残す(貸借の動きが読める)
  • fly-pill(飛んでくるピル): トグル対象(OFF で即時反映)

ラベルも「アニメーション ON/OFF」から「着弾アニメ」に変えた。何が切れるかをトグル名そのものから読めるようにした。

学び: スコープを切る指示は『何を残したいか』から書く

最初の指示「アニメーション ON/OFF」は、削りたい対象を消去法で書いていた。Claude Code は素直に解釈して全部止めた。差し戻し後の指示「fly-pill だけ切って、カウントアップ・ハイライト・delta popup は残せ」が出てきて、はじめて狙いどおりの形に収束した。

人間が「動きが多すぎる」と感じている時、何を消したいかは漠然としているが、何を残したいかは結構ハッキリ分かる。最初から「これとこれは残してほしい」と書いた方が、AI に渡す指示として一発で通る。次回以降、UI の引き算依頼では「残す側」を明示する。

ESLint 既存エラー2件は別タスクに切り出して Codex レビュー通過

修正を入れ終えて lint を回したら、警告が2件残っていた。両方とも @typescript-eslint/no-dynamic-delete ルール違反。今回の変更で増えたものではなく、以前からの既存エラー。

「そのままやっちゃった方が早いか、別タスクに切り出すか」を迷ったが、内容を読んで動的キーで delete している箇所が複数ファイルにまたがっていたので別タスクに切り出すと判断した。

  • マークダウンで詳細記述(修正方針・対応箇所・テスト観点)
  • Codex CLI に「致命的な点だけ指摘して」とレビュー依頼
  • 1回目: 致命的指摘2件 → プラン更新
  • 2回目(resume --last で同コンテキスト継続): 通過

確定したプランは memo/2026-05-11/lint-no-dynamic-delete-fix.md に保存。今日は対応せず、別セッションで切り替えて手をつける。

修正サマリ

  • pendingApply.value 中の clearChanged 適用 → 前問ハイライト残留バグ修正
  • 感情科目のプラス→緑、マイナス→赤を着弾の背景色に反映
  • 「着弾アニメ」ON/OFF トグルを追加(C/S トグルと同じデザインで配置)
  • トグルの作用範囲を fly-pill のみに絞る(カウントアップ・ハイライト・delta popup は常時表示)
  • ESLint 既存エラー2件は別タスクに切り出し、Codex レビュー通過済みプランを memo/2026-05-11/lint-no-dynamic-delete-fix.md に保存

振り返り

  • 画面の違和感は仕様書には書いていない。前問のハイライトが消えないバグも、着弾アニメがしつこい問題も、自分が画面を触って初めて気づいた。AI が書いた UI ロジックでも、最終的に「目で見て違和感を拾う係」は人間に残る
  • AI への引き算指示は『残す側』を書く。「全部 OFF にして」と頼むと本当に全部消えるので、消したい1要素を名指しした方が早い
  • 既存 lint エラーの扱いは、ファイル数で判断する。今回は複数ファイルに散っていたので別タスク化した。1ファイル内で完結なら同セッションで片付けてもよかった