[{"data":1,"prerenderedAt":280},["ShallowReactive",2],{"content-/textbook-quiz-twocolumn-memo-viewer":3,"all-pages-for-dir":278,"og-image-/textbook-quiz-twocolumn-memo-viewer":279},{"id":4,"title":5,"body":6,"category":260,"description":261,"extension":262,"meta":263,"navigation":231,"ogImage":264,"path":265,"project_name":266,"published":267,"publishedAt":268,"seo":269,"stem":270,"tags":271,"todo":264,"unpublished":267,"updatedAt":264,"__hash__":277},"pages/2026-05/2026-05-18/textbook-quiz-twocolumn-and-memo-viewer.md","教科書とクイズを Part 1/2 の2カラムに整え、ローカルのマークダウンビューアまで作った",{"type":7,"value":8,"toc":246},"minimark",[9,14,18,21,33,36,43,46,49,56,75,79,82,96,99,102,109,128,131,135,146,149,152,159,162,189,192,217,220],[10,11,13],"h2",{"id":12},"きっかけ縦に伸びた-index-ページ","きっかけ：縦に伸びた index ページ",[15,16,17],"p",{},"決算書を読む教科書の index ページを開いて、スクロールバーが画面の右端で短く縮こまっているのを見つけた。Part 1 と Part 2 が縦に積まれていて、PC のワイドな横幅がまるごと余白になっていた。モバイルでは1カラムでいいが、PC で同じレイアウトを流すと「下にもっとある」というシグナルが弱い。",[15,19,20],{},"直す方針を決めた。PC幅では2カラム、モバイル ≤960px では1カラムに崩れるグリッドラッパー。Claude Code に「textbook の index を Part 1/2 で2カラムに、960px 以下で1カラムに畳んで」と渡して実装させた。",[15,22,23,24,28,29,32],{},"ここで一瞬迷ったのは、Part 2 の章番号を CH08〜のまま続けるか、Part 2 内で CH01 から振り直すかだった。リナンバーすれば「Part 2 単独」として綺麗に見えるが、URL・",[25,26,27],"code",{},"textbookChapters","・",[25,30,31],{},"quizRegistry","・ファイル名を全部書き換える大手術になる。Part 2 は Part 1 の続編という積み上げ関係なので、通し番号のまま据え置くと決めた。意思決定としては5秒で済んだが、後から「やっぱり振り直そう」と戻ると半日溶ける類の選択だった。",[10,34,35],{"id":35},"積み残しを書き出させる",[15,37,38,39,42],{},"ここで「ついでに細かい改善を片付けたい」と思ったが、頭の中の TODO リストが既に曖昧だった。Claude Code に「今のリポジトリを舐めて、積み残しっぽい改善ポイントを ",[25,40,41],{},"memo/2026-05-18/00-backlog.md"," に書き出して」と振った。",[15,44,45],{},"返ってきたのは10件強の箇条書き。クイズ index も2カラムにすべき、教科書ページにパンくずが無い、view ページに目次が欲しい、トップから memo に飛ぶ動線が無い、など。優先度順に並んでいたので、上から潰してと指示して、5件をひと続きのコミットで処理させた。",[10,47,48],{"id":48},"ローカル専用のマークダウンビューア",[15,50,51,52,55],{},"backlog の中に「memo/ 配下を毎回 VSCode で開くのが面倒、ブラウザで読みたい」が混ざっていた。",[25,53,54],{},"marked"," が既に依存として入っていたので、本番ビルドからは除外する dev 限定ページとして作ることにした。",[15,57,58,59,62,63,66,67,70,71,74],{},"実装は ",[25,60,61],{},"import.meta.dev"," ガードで本番ルートから完全に剥がす方針。Claude Code に「dev だけで ",[25,64,65],{},"/dev/memo"," 配下を歩いて、",[25,68,69],{},"memo/"," の中身を一覧表示できるツリー＋ビューを作って」と頼んだ。ファイル一覧 API、view API、view ページの3点セットが20分で揃った。トップページにも ",[25,72,73],{},"v-if=\"isDev\""," でガードした「📓 memo ビューア」カードを追加して、localhost で開いた時だけ顔を出すようにした。",[10,76,78],{"id":77},"hmr-無限再ビルドを止める","HMR 無限再ビルドを止める",[15,80,81],{},"書き終えて dev サーバーを再起動した。コンソールに「Nuxt Nitro server built」が連発し始めた。1秒に1回ペースで再ビルドが走り、ターミナルが緑色の文字で埋まっていく。",[15,83,84,85,87,88,91,92,95],{},"切り分けに入った。",[25,86,69],{}," にファイルを追加したタイミングで vite/nitro の watch が反応していた。",[25,89,90],{},"audio-assets/"," も同じ症状を起こしていた。Nuxt の watch 対象から両ディレクトリを ignore する設定を ",[25,93,94],{},"nuxt.config.ts"," に追加して、ようやく再ビルドが止まった。緑文字が静かになった瞬間に、ファンの音が落ちて部屋が一段静かになった。",[10,97,98],{"id":98},"目次のハイライトが効かない",[15,100,101],{},"view ページに右サイドバー目次を生やした。H1〜H3 を抽出して、sticky で追従させて、日本語の見出しでも安全にアンカー化する。ここまでは10分で動いた。",[15,103,104,105,108],{},"問題は「スクロールに合わせて active のハイライトを淡いピンクで光らせる」処理だった。実装は入れたのに、スクロールしても色が動かない。クリックでジャンプは効く。",[25,106,107],{},"IntersectionObserver"," も生きている、ように見える。",[15,110,111,112,115,116,119,120,123,124,127],{},"console.log を仕込んで原因を追った。setup が一度だけ走って、observer が登録される前に終わっていた。",[25,113,114],{},"await useFetch(...)"," を setup の冒頭に書いていたせいで、setup が async になり、client side の継続部分が走らない構造になっていた。",[25,117,118],{},"await"," を外して、",[25,121,122],{},"useFetch"," の戻り値を ",[25,125,126],{},".data"," 越しに watch する形に直したら、スクロールに合わせて目次の項目がピンクに光り始めた。",[15,129,130],{},"「async setup と client-only な副作用は混ぜるな」を体で覚え直した一件。SSR 文脈では当たり前の話なのに、書いている最中はうっかりやる。",[10,132,134],{"id":133},"クイズ-index-とトーンを揃える","クイズ index とトーンを揃える",[15,136,137,138,141,142,145],{},"教科書の index が綺麗になると、隣のクイズ index が急に古く見えた。Part 2 のアクセントカラー、フォント、",[25,139,140],{},"part-header"," の組み方、",[25,143,144],{},"secondary-link"," のホバー挙動、全部が微妙にズレている。同じ「Part 1 / Part 2 の2カラム」に揃えて、CSS の値もコピペで合わせた。",[15,147,148],{},"内部の topic 番号は据え置いた。リナンバーは教科書側で却下したのと同じ理由だ。代わりに、各クイズカードに「📖 対応 CH8 / CH9 / CH12」というバッジを足した。5-1〜5-7 の Part 1 分析セクションには CH06（マゼンタ）と CH10（紺）の両 Part バッジが並ぶ。8-1 営業 CF には CH08 + CH09 + CH12 の紺バッジが3つ刺さる。クイズと教科書の対応関係が、目で1秒で取れるようになった。",[10,150,151],{"id":151},"パンくず移植",[15,153,154,155,158],{},"仕上げに教科書ページのパンくずリストを追加した。クイズ側に同じ仕組みが既にあったので、Claude Code に「クイズのパンくずを教科書ページに流用して」と渡した。",[25,156,157],{},"/textbook/ch08/01"," のような階層を、トップ → 教科書 → Part 2 → CH08 → 01 と辿れるリンクとして頭に表示する。これも10分で終わった。",[10,160,161],{"id":161},"今日のコミット履歴",[163,164,165,169,174,177,180,183,186],"ol",{},[166,167,168],"li",{},"textbook index を Part 1/2 の2カラムに変更（960px で1カラム）",[166,170,171,173],{},[25,172,65],{}," ローカルマークダウンビューアを新規追加",[166,175,176],{},"nuxt.config の watch から memo/ と audio-assets/ を ignore",[166,178,179],{},"view ページに右サイドバー目次 + active ハイライトを実装",[166,181,182],{},"quiz index を textbook と同じ2カラムに揃え、CH バッジを追加",[166,184,185],{},"教科書ページにパンくずリストを移植",[166,187,188],{},"トップに dev 限定 memo ビューアカードを追加",[10,190,191],{"id":191},"学び",[193,194,195,198,201,207,214],"ul",{},[166,196,197],{},"横並びにできる場所を縦に積んだままにすると、PC でユーザーが「下にもっとある」を見落とす。ワイヤレベルの2カラム化は ROI が高い",[166,199,200],{},"通し番号 vs リナンバーは、URL とデータ構造への波及で判断する。見た目だけで動かしてはいけない",[166,202,203,204,206],{},"本番に出したくない開発支援 UI は ",[25,205,61],{}," で物理的に剥がす。CSS で隠すと bundle に残る",[166,208,209,210,213],{},"async setup と client-only な副作用を混ぜると、observer や watcher が登録される前に setup が終わる。",[25,211,212],{},"await useFetch"," は安易に書かない",[166,215,216],{},"HMR が暴走したら、watch 対象に余計なディレクトリが混ざっていないかを真っ先に疑う",[10,218,219],{"id":219},"明日以降の積み残し",[193,221,224,234,240],{"className":222},[223],"contains-task-list",[166,225,228,233],{"className":226},[227],"task-list-item",[229,230],"input",{"disabled":231,"type":232},true,"checkbox"," memo ビューアのツリーで、フォルダの開閉状態を localStorage に保存する",[166,235,237,239],{"className":236},[227],[229,238],{"disabled":231,"type":232}," 目次の active ハイライトを、見出し直下のセクション末尾まで延長する（今は次の見出しに乗った瞬間に切り替わる）",[166,241,243,245],{"className":242},[227],[229,244],{"disabled":231,"type":232}," クイズ index の CH バッジを、クリックで対応する教科書ページにジャンプできるリンクに昇格させる",{"title":247,"searchDepth":248,"depth":248,"links":249},"",2,[250,251,252,253,254,255,256,257,258,259],{"id":12,"depth":248,"text":13},{"id":35,"depth":248,"text":35},{"id":48,"depth":248,"text":48},{"id":77,"depth":248,"text":78},{"id":98,"depth":248,"text":98},{"id":133,"depth":248,"text":134},{"id":151,"depth":248,"text":151},{"id":161,"depth":248,"text":161},{"id":191,"depth":248,"text":191},{"id":219,"depth":248,"text":219},"dev","決算書を読む教科書とクイズの index を Part 1/2 の2カラムに直し、ローカル専用のマークダウンビューアを生やし、目次のスクロール追従ハイライトまで仕込んだ早朝の積み残し潰し。","md",{},null,"/textbook-quiz-twocolumn-memo-viewer","eurekapu-nuxt4",false,"2026-05-18T00:00:00.000Z",{"title":5,"description":261},"2026-05/2026-05-18/textbook-quiz-twocolumn-and-memo-viewer",[272,273,274,275,276],"Nuxt","Vue","Layout","UI改善","dev環境","jihqC-rmxoNAA6zZiRD_SVXubP-sWBVBqlcqL1NaUcc",[],"https://log.eurekapu.com/og/blog/textbook-quiz-twocolumn-memo-viewer.png?v=2026-05-18T00%3A00%3A00.000Z&title=%E6%95%99%E7%A7%91%E6%9B%B8%E3%81%A8%E3%82%AF%E3%82%A4%E3%82%BA%E3%82%92%20Part%201%2F2%20%E3%81%AE2%E3%82%AB%E3%83%A9%E3%83%A0%E3%81%AB%E6%95%B4%E3%81%88%E3%80%81%E3%83%AD%E3%83%BC%E3%82%AB%E3%83%AB%E3%81%AE%E3%83%9E%E3%83%BC%E3%82%AF%E3%83%80%E3%82%A6%E3%83%B3%E3%83%93%E3%83%A5%E3%83%BC%E3%82%A2%E3%81%BE%E3%81%A7%E4%BD%9C%E3%81%A3%E3%81%9F&author=Kei%20Komatsu&sig=7cd2291822a9bbb2",1782528839238]