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 を入れて、ジャンプを和らげる