[{"data":1,"prerenderedAt":630},["ShallowReactive",2],{"content-/investment-quiz-2col-refactor":3,"all-pages-for-dir":628,"og-image-/investment-quiz-2col-refactor":629},{"id":4,"title":5,"body":6,"category":609,"description":610,"extension":611,"meta":612,"navigation":574,"ogImage":613,"path":614,"project_name":615,"published":616,"publishedAt":617,"seo":618,"stem":619,"tags":620,"todo":613,"unpublished":616,"updatedAt":613,"__hash__":627},"pages/2026-05/2026-05-14/investment-quiz-2col-refactor.md","投資判断クイズを2カラムレイアウトへ移行：1ページ完成→コンポーネント化→横展開",{"type":7,"value":8,"toc":599},"minimark",[9,13,22,26,41,107,110,114,117,127,131,134,151,162,240,250,254,257,263,272,374,377,381,388,503,517,520,533,536,560,563,595],[10,11,5],"h1",{"id":12},"投資判断クイズを2カラムレイアウトへ移行1ページ完成コンポーネント化横展開",[14,15,16,17,21],"p",{},"午前にPart 2投資判断クイズの74問とSVG18枚を流し込み終え、午後はUX改善に切り替えた。",[18,19,20],"code",{},"/financial-statements-quiz/investment/01-operating-cf"," を開いて指を止めた瞬間、画面の上下にスクロールしないと届かない余白が広がっていた。「ここってなんでこんなにスペース空いてるんですかね」と打ち込んだのが、今日の作業の起点になった。",[23,24,25],"h2",{"id":25},"スペースの正体を掘る",[14,27,28,29,32,33,36,37,40],{},"Claude Code に CSS を追わせると、原因はすぐ出てきた。",[18,30,31],{},".practice-list"," に ",[18,34,35],{},"padding-top: 50vh"," と ",[18,38,39],{},"padding-bottom: 50vh"," が積まれている。矢印キー（↑↓/jk）でクイズを切り替えるとき、選択中の問題を画面中央に持ってくるためのバッファだった。",[42,43,48],"pre",{"className":44,"code":45,"language":46,"meta":47,"style":47},"language-css shiki shiki-themes vitesse-light vitesse-light",".practice-list {\n  padding-top: 50vh;\n  padding-bottom: 50vh;\n}\n","css","",[18,49,50,66,87,101],{"__ignoreMap":47},[51,52,55,59,63],"span",{"class":53,"line":54},"line",1,[51,56,58],{"class":57},"shFtX",".",[51,60,62],{"class":61},"s4oTP","practice-list",[51,64,65],{"class":57}," {\n",[51,67,69,73,76,80,84],{"class":53,"line":68},2,[51,70,72],{"class":71},"sz8Xr","  padding-top",[51,74,75],{"class":57},":",[51,77,79],{"class":78},"sM54T"," 50",[51,81,83],{"class":82},"stQ0i","vh",[51,85,86],{"class":57},";\n",[51,88,90,93,95,97,99],{"class":53,"line":89},3,[51,91,92],{"class":71},"  padding-bottom",[51,94,75],{"class":57},[51,96,79],{"class":78},[51,98,83],{"class":82},[51,100,86],{"class":57},[51,102,104],{"class":53,"line":103},4,[51,105,106],{"class":57},"}\n",[14,108,109],{},"理屈は通っている。ただ、キーボード操作前提のUXがマウス操作のユーザーには「無駄に空いた画面」として刺さる。原因が見えても、これを潰すだけでは要件が満たせないとすぐ気付いた。",[23,111,113],{"id":112},"本当の要件は-basics-ページのux移植だった","本当の要件は basics ページのUX移植だった",[14,115,116],{},"頭の中にあった理想形は、すでに basics ページで動いていた2カラムレイアウトだった。左に解説図を固定し、右にクイズリストを独立スクロールさせる構成。投資クイズもこれに揃えたい、というのが本音だった。スペースを詰めるのではなく、画面そのものの組み方を入れ替える話だった。",[14,118,119,122,123,126],{},[18,120,121],{},"QuizPage"," コンポーネントは basics 側ですでに動いている。これを使って ",[18,124,125],{},"01-operating-cf.vue"," を書き換えるところから着手した。",[23,128,130],{"id":129},"_1ページだけ先に仕上げる","1ページだけ先に仕上げる",[14,132,133],{},"横展開する前に、1ページを完成形にする方針で進めた。",[135,136,137,145,148],"ul",{},[138,139,140,141,144],"li",{},"左ペイン: ",[18,142,143],{},"Part2OcfVsNetIncome"," の SVG を固定",[138,146,147],{},"右ペイン: Q1〜Q4 を独立スクロールで並べる",[138,149,150],{},"選択中の問題に応じて左ペインの図がマゼンタで強調される",[14,152,153,154,157,158,161],{},"ここで詰まったのが ",[18,155,156],{},"highlight: null"," のケースだった。Q1/Q3/Q4 はハイライト対象がなく、左ペインに「問題文がない問題」を出すと違和感が残る。プレースホルダーとして薄い文字だけを出す方針に変え、CSS の ",[18,159,160],{},":has()"," セレクタで対応した。",[42,163,165],{"className":44,"code":164,"language":46,"meta":47,"style":47},".quiz-page:has(.quiz-card[data-highlight=\"null\"].is-active) .left-pane {\n  flex-basis: 30%;\n}\n",[18,166,167,221,236],{"__ignoreMap":47},[51,168,169,171,174,176,179,182,185,188,191,194,198,202,204,207,210,213,216,219],{"class":53,"line":54},[51,170,58],{"class":57},[51,172,173],{"class":61},"quiz-page",[51,175,75],{"class":57},[51,177,178],{"class":61},"has",[51,180,181],{"class":57},"(.",[51,183,184],{"class":61},"quiz-card",[51,186,187],{"class":57},"[",[51,189,190],{"class":61},"data-highlight",[51,192,193],{"class":82},"=",[51,195,197],{"class":196},"sMJiu","\"",[51,199,201],{"class":200},"sdGka","null",[51,203,197],{"class":196},[51,205,206],{"class":57},"].",[51,208,209],{"class":61},"is-active",[51,211,212],{"class":57},")",[51,214,215],{"class":57}," .",[51,217,218],{"class":61},"left-pane",[51,220,65],{"class":57},[51,222,223,226,228,231,234],{"class":53,"line":68},[51,224,225],{"class":71},"  flex-basis",[51,227,75],{"class":57},[51,229,230],{"class":78}," 30",[51,232,233],{"class":82},"%",[51,235,86],{"class":57},[51,237,238],{"class":53,"line":89},[51,239,106],{"class":57},[14,241,242,243,246,247,249],{},"選択中のカードが ",[18,244,245],{},"data-highlight=\"null\""," のときだけ左ペインを縮めて、右の問題文を広く読ませる。Q2 を選ぶと左ペインが元のサイズに戻り、",[18,248,143],{}," の C 社（粉飾サイン）にマゼンタが当たる。図と問題のリンクが視覚的につながった瞬間、自分でも「これだ」と声が出た。",[23,251,253],{"id":252},"最後の問題を解いたら次のトピックへ","「最後の問題を解いたら次のトピックへ」",[14,255,256],{},"1ページが固まったところで、追加の要望を出した。",[258,259,260],"blockquote",{},[14,261,262],{},"最後の問題を解いたら自動で次のトピックへ遷移してほしい。あと 8-1 から 8-18 まで全部に適用したいので、コンポーネント化して。",[14,264,265,267,268,271],{},[18,266,121],{}," に自動遷移を仕込んだ。最後の問題を解いた瞬間に5秒のタイマーを張り、次トピックへ ",[18,269,270],{},"navigateTo"," する。",[42,273,277],{"className":274,"code":275,"language":276,"meta":47,"style":47},"language-ts shiki shiki-themes vitesse-light vitesse-light","watch(isAllSolved, (solved) => {\n  if (!solved || !props.nextPath) return\n  setTimeout(() => navigateTo(props.nextPath), 5000)\n})\n","ts",[18,278,279,307,339,369],{"__ignoreMap":47},[51,280,281,285,288,291,294,297,300,302,305],{"class":53,"line":54},[51,282,284],{"class":283},"senZ8","watch",[51,286,287],{"class":57},"(",[51,289,290],{"class":61},"isAllSolved",[51,292,293],{"class":57},",",[51,295,296],{"class":57}," (",[51,298,299],{"class":61},"solved",[51,301,212],{"class":57},[51,303,304],{"class":57}," =>",[51,306,65],{"class":57},[51,308,309,313,315,318,320,323,326,329,331,334,336],{"class":53,"line":68},[51,310,312],{"class":311},"sHkkW","  if",[51,314,296],{"class":57},[51,316,317],{"class":82},"!",[51,319,299],{"class":61},[51,321,322],{"class":82}," ||",[51,324,325],{"class":82}," !",[51,327,328],{"class":61},"props",[51,330,58],{"class":57},[51,332,333],{"class":61},"nextPath",[51,335,212],{"class":57},[51,337,338],{"class":311}," return\n",[51,340,341,344,347,349,352,354,356,358,360,363,366],{"class":53,"line":89},[51,342,343],{"class":283},"  setTimeout",[51,345,346],{"class":57},"(()",[51,348,304],{"class":57},[51,350,351],{"class":283}," navigateTo",[51,353,287],{"class":57},[51,355,328],{"class":61},[51,357,58],{"class":57},[51,359,333],{"class":61},[51,361,362],{"class":57},"),",[51,364,365],{"class":78}," 5000",[51,367,368],{"class":57},")\n",[51,370,371],{"class":53,"line":103},[51,372,373],{"class":57},"})\n",[14,375,376],{},"5秒は迷った。3秒だと「もう一度見たい」が間に合わない。10秒だと止まったように感じる。Q2を解いた直後の自分の視線移動を見て、図を一度見返してから次に行く動作が約4秒だったので、5秒に落とした。",[23,378,380],{"id":379},"investmenttopicpage-で18ページに敷く","InvestmentTopicPage で18ページに敷く",[14,382,383,384,387],{},"横展開のために、共通ラッパー ",[18,385,386],{},"InvestmentTopicPage.vue"," を切り出した。トピック番号・タイトル・SVGコンポーネント・問題配列・次トピックへのパスを受け取るだけのシェルに仕上げた。",[42,389,393],{"className":390,"code":391,"language":392,"meta":47,"style":47},"language-vue shiki shiki-themes vitesse-light vitesse-light","\u003Ctemplate>\n  \u003CQuizPage\n    :topic-id=\"topicId\"\n    :title=\"title\"\n    :svg-component=\"svgComponent\"\n    :questions=\"questions\"\n    :next-path=\"nextPath\"\n  />\n\u003C/template>\n","vue",[18,394,395,406,414,429,443,458,473,487,493],{"__ignoreMap":47},[51,396,397,400,403],{"class":53,"line":54},[51,398,399],{"class":57},"\u003C",[51,401,402],{"class":311},"template",[51,404,405],{"class":57},">\n",[51,407,408,411],{"class":53,"line":68},[51,409,410],{"class":57},"  \u003C",[51,412,413],{"class":311},"QuizPage\n",[51,415,416,419,421,423,426],{"class":53,"line":89},[51,417,418],{"class":61},"    :topic-id",[51,420,193],{"class":57},[51,422,197],{"class":196},[51,424,425],{"class":200},"topicId",[51,427,428],{"class":196},"\"\n",[51,430,431,434,436,438,441],{"class":53,"line":103},[51,432,433],{"class":61},"    :title",[51,435,193],{"class":57},[51,437,197],{"class":196},[51,439,440],{"class":200},"title",[51,442,428],{"class":196},[51,444,446,449,451,453,456],{"class":53,"line":445},5,[51,447,448],{"class":61},"    :svg-component",[51,450,193],{"class":57},[51,452,197],{"class":196},[51,454,455],{"class":200},"svgComponent",[51,457,428],{"class":196},[51,459,461,464,466,468,471],{"class":53,"line":460},6,[51,462,463],{"class":61},"    :questions",[51,465,193],{"class":57},[51,467,197],{"class":196},[51,469,470],{"class":200},"questions",[51,472,428],{"class":196},[51,474,476,479,481,483,485],{"class":53,"line":475},7,[51,477,478],{"class":61},"    :next-path",[51,480,193],{"class":57},[51,482,197],{"class":196},[51,484,333],{"class":200},[51,486,428],{"class":196},[51,488,490],{"class":53,"line":489},8,[51,491,492],{"class":57},"  />\n",[51,494,496,499,501],{"class":53,"line":495},9,[51,497,498],{"class":57},"\u003C/",[51,500,402],{"class":311},[51,502,405],{"class":57},[14,504,505,506,508,509,512,513,516],{},"各ページ（",[18,507,125],{}," 〜 ",[18,510,511],{},"18-...vue","）は ",[18,514,515],{},"InvestmentTopicPage"," に props を渡すだけになった。1ページあたり10行を切るところまで削れた。",[23,518,519],{"id":519},"使用制限が近づいて打ち切り",[14,521,522,523,526,527,529,530,532],{},"横展開を始めたところで使用制限が見えてきた。残り17ページを今日中に終わらせるのは諦めて、",[18,524,525],{},"memo/2026-05-14/investment-quiz-2col-migration-progress.md"," に進捗を書き残した。どのページを差し替え済みで、どのページが未着手か、",[18,528,515],{}," を使うときに気を付ける点（SVGコンポーネントの import パス、",[18,531,333],{}," の終端処理）まで残しておけば、明日の自分が迷わない。",[23,534,535],{"id":535},"今日の学び",[135,537,538,545,548,557],{},[138,539,540,541,544],{},"AI 実装でも UX の違和感は人間が拾う係。「スペースが空いてる」の一言が出なければ、",[18,542,543],{},"padding: 50vh"," は仕様として生き残っていた",[138,546,547],{},"原因と要件は別物。スペースを詰める修正ではなく、レイアウト構成そのものを入れ替える要件に切り替えた瞬間、作業の方向が定まった",[138,549,550,551,553,554,556],{},"コンポーネント化のタイミングは1ページ完成後がよい。最初から汎用化を狙うと、",[18,552,160],{}," セレクタや ",[18,555,156],{}," のような実装ディテールが見えないまま抽象化してしまう",[138,558,559],{},"自動遷移のタイマーは、自分の視線移動を計測してから決める。秒数を決めるのに「ちょうどいい」で済ませると、後で必ず触り直すことになる",[23,561,562],{"id":562},"明日やること",[135,564,567,580,589],{"className":565},[566],"contains-task-list",[138,568,571,576,577,579],{"className":569},[570],"task-list-item",[572,573],"input",{"disabled":574,"type":575},true,"checkbox"," 残り17ページ（02-... 〜 18-...）を ",[18,578,515],{}," で書き換える",[138,581,583,585,586,588],{"className":582},[570],[572,584],{"disabled":574,"type":575}," 最終トピック（18番）の ",[18,587,333],{}," を「Part 2 完了画面」へ向ける",[138,590,592,594],{"className":591},[570],[572,593],{"disabled":574,"type":575}," 自動遷移5秒のあいだ、画面下に「次へ進みます」のカウントダウン表示を出す",[596,597,598],"style",{},"html pre.shiki code .shFtX, html code.shiki .shFtX{--shiki-default:#999999;--shiki-dark:#999999}html pre.shiki code .s4oTP, html code.shiki .s4oTP{--shiki-default:#B07D48;--shiki-dark:#B07D48}html pre.shiki code .sz8Xr, html code.shiki .sz8Xr{--shiki-default:#998418;--shiki-dark:#998418}html pre.shiki code .sM54T, html code.shiki .sM54T{--shiki-default:#2F798A;--shiki-dark:#2F798A}html pre.shiki code .stQ0i, html code.shiki .stQ0i{--shiki-default:#AB5959;--shiki-dark:#AB5959}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sMJiu, html code.shiki .sMJiu{--shiki-default:#B5695977;--shiki-dark:#B5695977}html pre.shiki code .sdGka, html code.shiki .sdGka{--shiki-default:#B56959;--shiki-dark:#B56959}html pre.shiki code .senZ8, html code.shiki .senZ8{--shiki-default:#59873A;--shiki-dark:#59873A}html pre.shiki code .sHkkW, html code.shiki .sHkkW{--shiki-default:#1E754F;--shiki-dark:#1E754F}",{"title":47,"searchDepth":68,"depth":68,"links":600},[601,602,603,604,605,606,607,608],{"id":25,"depth":68,"text":25},{"id":112,"depth":68,"text":113},{"id":129,"depth":68,"text":130},{"id":252,"depth":68,"text":253},{"id":379,"depth":68,"text":380},{"id":519,"depth":68,"text":519},{"id":535,"depth":68,"text":535},{"id":562,"depth":68,"text":562},"dev","Part 2投資判断クイズの18ページを2カラムUXに移行する作業ログ。スペース過多の違和感から要件を掘り起こし、QuizPageとInvestmentTopicPageに切り出して横展開した。","md",{},null,"/investment-quiz-2col-refactor","eurekapu-nuxt4",false,"2026-05-14T00:00:00.000Z",{"title":5,"description":610},"2026-05/2026-05-14/investment-quiz-2col-refactor",[621,622,623,624,625,626],"Nuxt","Vue","UX","リファクタリング","簿記クイズ","コンポーネント設計","XOfi3YEVkWl05wScszNlRiht3SUpgsvqx90jMhBaNus",[],"https://log.eurekapu.com/og/blog/investment-quiz-2col-refactor.png?v=2026-05-14T00%3A00%3A00.000Z&title=%E6%8A%95%E8%B3%87%E5%88%A4%E6%96%AD%E3%82%AF%E3%82%A4%E3%82%BA%E3%82%922%E3%82%AB%E3%83%A9%E3%83%A0%E3%83%AC%E3%82%A4%E3%82%A2%E3%82%A6%E3%83%88%E3%81%B8%E7%A7%BB%E8%A1%8C%EF%BC%9A1%E3%83%9A%E3%83%BC%E3%82%B8%E5%AE%8C%E6%88%90%E2%86%92%E3%82%B3%E3%83%B3%E3%83%9D%E3%83%BC%E3%83%8D%E3%83%B3%E3%83%88%E5%8C%96%E2%86%92%E6%A8%AA%E5%B1%95%E9%96%8B&author=Kei%20Komatsu&sig=c776e9366d1c5735",1782528836514]