開発eurekapu-nuxt4メモ

3表がバラバラだった

/quiz/practice のクイズ画面は、財務諸表の表示を BS/PL/CS の3コンポーネントで担っていたが、見た目が三者三様だった。BS は左右2列、PL は上から積み上げ、CS は別レイアウト。それぞれカード枠で囲まれていて、フォントサイズも揃っておらず、画面に並べると「3つ別の画面が並んでいる」ように見えた。

学習者の視点で見ると、PL の当期純利益が BS の繰越利益剰余金に流れるという縦の連携が、この見た目では伝わらない。同じ世界の数字が3面に映っていることを、見た目から伝えたかった。

/lessons/financial-statements/cockpit-00-summary で先に作ってあったコクピット風スタイル(タイトルバー #d1d5db・テーブルベース・GL階調・カード枠なし・フォント 0.825rem)に、quiz 側の3コンポーネントを丸ごと寄せる方針にした。


BS は「合計を上、内訳を下」に組み替えた

BS は従来「資産は左、負債純資産は右」の左右2列だった。これをコクピット形式の縦1列に合わせるため、構造を組み替えた。

最上段に資産合計負債純資産合計を置いて、その下にブレイクダウンしていく形にした。

資産合計 = 負債純資産合計        ← 一番上
├─ 流動資産合計
│   ├─ 現金及び預金
│   ├─ 売掛金
│   └─ その他の流動資産
├─ 固定資産合計
│   └─ ...
├─ 流動負債合計
│   └─ ...
└─ 純資産合計

「上から順に内訳を開いていく」読み方に統一した結果、PL/CS と縦軸が揃って画面の視線移動が一方向になった。

マイナス表記もこのタイミングで全箇所「▲」に統一した。-1,000△1,000▲1,000 が3コンポーネントで混在していて、視覚的なノイズになっていた。


CS表示時だけ画面を広げる — 「全画面が広がってうざい」問題

CS は科目数が多く、3列(営業/投資/財務)あるため、デフォルトの max-width: 1024px のままだと CS だけ窮屈だった。

最初は「CS 表示中はページ全体を 1480px に広げる」実装にしたら、ヘッダー(累積/単体/CS表示ボタン)まで一緒に広がってボタンが間延びした。全画面が広がってうざいという違和感が拭えなかった。

ヘッダーは max-width: 1024px を維持して、財務三表エリア(body)だけ親の枠を突き抜けてブレイクアウトする形に変更した。

.fs-area {
  max-width: 1480px;
  margin-left: calc(50% - min(50vw - 1rem, 740px));
  margin-right: calc(50% - min(50vw - 1rem, 740px));
}

50%50vw の差で親要素の中央から viewport 中央までのオフセットを取り、ネガティブマージンで親を突き抜ける。CS 非表示時は max-width: 1024px に戻る。ヘッダーは動かず、body だけがフワッと広がる挙動になった。


delta-popup — 数字が変わったら浮き上がる

数値が変化したことを学習者に伝えるため、変化量を「+1,000」「▲500」と数字の右上に浮上させて消える delta-popup を BS/PL/CS の3コンポーネントに入れた。

最初の実装では、流動資産合計や資産合計といった集計値の上にも delta-popup が出た。集計値は内訳科目が動けば自動で動くため、内訳と合計の両方でポップアップが出ると画面が花火大会になり、どこに注目していいか分からなくなった。

科目に acct: prefix を付けたものだけポップアップを発火するように制限した。

<DeltaPopup
  v-if="row.id.startsWith('acct:')"
  :value="row.value"
/>

集計値(total:subtotal: prefix)は静かに動き、個別科目だけが「+1,000」と浮かぶ。視線が個別科目に集まり、その後で合計が連動して動く順番に整った。


3表をつなぐ装飾点線 — match-cue overlay

3表が別画面に見える問題は構造で半分解決したが、もう半分は「数字の連携」をどう見せるかだった。CockpitMatchCueOverlay.vue を quiz 側に移植して、3組の点線を引いた。

結ぶ箇所意味
PL 当期純利益 → BS 当期純利益オレンジ損益が純資産に振り替わる
PL 税引前 → CS 間接法税引前間接法のスタート点
CS 期末現金 → BS 現金及び預金ティール期末残高と BS 現金が一致する

点線は SVG overlay で、3表の DOM 要素から getBoundingClientRect() を取って端点を計算する。3組同時に表示するとうるさいので、シーケンス制御を入れた。

  • Next/Back で問題を切り替えると全リセット(点線は0本)
  • 解答後、カウントアップアニメーション(1.5s)が完了
  • そこから 200ms 待って、1本ずつ描画開始(t = 1700ms で1本目、以後一定間隔)

カウントアップ中に点線が出ると、数字が動いている最中に注意が分散する。「数字が止まってから線を引く」順序にしたら、視線が「動いた数字 → どこにつながったか」の順で流れた。


キーボードショートカット — マウスから手を離さなくていい

クイズを連打する学習者が、毎回ボタンにカーソルを運ぶのが面倒だった。3つだけショートカットを足した。

キー動作
前の問題
次の問題
Ctrl+Enter解答&解説

ボタンには <kbd> でキーラベルを表示して、初見でも気付けるようにした。

<button @click="next">
  次の問題 <kbd>→</kbd>
</button>

window.addEventListener('keydown') で拾って、<input><textarea> にフォーカスがある時はスキップ。Mac 用に Cmd+Enter も並列で受ける(event.metaKey || event.ctrlKey)。


担当分のみコミット

並行で他の変更(shogi 関連)が走っていたので、コミットは quiz 関連のファイルだけに絞った。git add -p で1ハンクずつ確認して、cockpit スタイル変換と delta-popup と match-cue overlay とキーボードショートカットの4テーマを4コミットに分割した。

作業ログは memo/2026-05-09/quiz-financial-statements-cockpit-style-worklog.md に残した。試行錯誤の脇道(最初は全画面ブレイクアウトしていた・delta-popup が集計値で発火していた)も全部書いておいた。同じ画面を半年後に触る時の自分への申し送りになる。


学びメモ

  • 「全画面が広がってうざい」を初手で実装したら、ヘッダーが間延びしてダサくなった。calc(50% - min(50vw - 1rem, 740px)) のネガティブマージンで body だけ親の枠を突き抜ける形に書き換えたら、ヘッダーは動かず body だけが広がるようになった。
  • delta-popup を全行に出した最初のバージョンは、画面が花火大会になって視線が定まらなかった。acct: prefix で個別科目だけに絞ったら、視線が「個別科目で動く → 合計が連動」の順に流れた。
  • match-cue overlay の点線は、カウントアップ中に出すと数字と線が同時に動いて注意が散った。t = 1700ms まで待って1本ずつ引くようにしたら、視線が一方向に流れた。
  • キーボードショートカットは <kbd> でボタンに表示しないと存在に気付かれない。実装と告知をセットにした。
  • マイナス表記の混在(-)は、コンポーネントごとに別の人が書くと必ず起きる。共通の formatter に集約してしまうのが結局速い。

次にやること

  • delta-popup の浮上速度・滞留時間を、簿記初学者にヒアリングして調整する
  • match-cue overlay の3組目(CS 期末現金 → BS 現金)が、画面下までスクロールしないと見えない問題を解決する。スクロール追従するかスナップする
  • キーボードショートカット(← → Ctrl+Enter)を /lessons/financial-statements/cockpit-00-summary 側にも横展開する
  • CS 非表示時の 1024px ↔ CS 表示時の 1480px の切り替えに 200ms の transition を入れて、ジャンプを和らげる