[[2026-01-04]] # 作業ログ 2026-01-04 ## 📋 概要(先頭数行で状況を把握) - ✅ 用語集(topics)の表示形式を統一(article-cardスタイル、折りたたみ可能に) - ✅ ビルドエラー修正(YAMLフロントマター重複削除、titleフィールド追加) - ✅ 関連コンテンツを展開時に全表示に変更(2段階クリック不要に) - ✅ ソートボタンの視覚的状態を修正(古い順/新しい順の見た目) - 🔄 ノートへのハッシュリンク実装(デバッグ中・保留) - 💡 プレビュー機能のアイデア検討(スマホ対応を含む) ## セッション詳細 ### 1. 用語集の表示形式統一 **背景**: videos/articlesと同じ「要約→クリックで展開」パターンに統一したい **実装内容**: #### HTMLの変更 (`index.astro`) **変更前**: ```html <div class="glossary-card"> <!-- 常に展開状態 --> </div> ``` **変更後**: ```html <article class="article-card" data-category={term.data.category}> <div class="article-header"> <div class="article-meta"> <span class="series-badge">📖 {term.data.category}</span> </div> <div class="article-title">{term.data.title}</div> <div class="article-description">{term.data.description}</div> </div> <div class="glossary-details"> <!-- 展開時のみ表示 --> </div> </article> ``` #### CSSの追加 ```css .glossary-details { display: none; opacity: 0; } .article-card.expanded .glossary-details { display: block; opacity: 1; } ``` #### JavaScriptの変更 ```javascript // 「すべて開く/閉じる」ボタンの対象に glossary を追加 const hasExpandableCards = currentMode === 'videos' || currentMode === 'articles' || currentMode === 'glossary'; ``` **結果**: videos, articles, topics が統一されたUI/UXで表示されるようになった --- ### 2. ビルドエラーの修正 **問題**: 複数のファイルでYAMLフロントマターのスキーマエラーが発生 #### エラー1: `topic` フィールドの重複 **ファイル例**: `250714_📅KS250714_長い時間の練習は、すればするほど下手になる.md` **原因**: ```yaml --- topic: 振り返り # ← 重複(1回目) topic_code: rev # ... topic: ['学習', '効率', '継続'] # ← 重複(2回目) --- ``` **修正**: 1つ目の `topic: 振り返り` を削除 #### エラー2: Obsidian Tips フォルダ内の53ファイルで `topic` 重複 **修正コマンド**: ```bash cd web/src/content/articles/Obsidian\ Tips for file in *.md; do sed -i '' '/^topic: Obsidian Tips$/d' "$file" done ``` #### エラー3: `title` フィールド欠落 **ファイル**: `ks.220506_💎ローカルの汎用ファイルを扱うことのメリット.md` **修正**: frontmatter に `title: ローカルの汎用ファイルを扱うことのメリット` を追加 **結果**: `npm run build` が成功(警告のみ) --- ### 3. 関連コンテンツの表示改善 **問題**: 用語集の関連コンテンツがボタンクリックで2段階表示されて不便 **変更内容**: **変更前**: ```html <button class="glossary-related-toggle"> 📚 関連コンテンツ (5件) ▼ </button> <div class="hidden"><!-- クリックで表示 --></div> ``` **変更後**: ```html <h4>📚 関連コンテンツ (5件)</h4> <div><!-- カード展開時に自動表示 --></div> ``` **削除したコード**: - `.glossary-related-toggle` のCSS - ボタンクリックイベントのJavaScript **結果**: 用語集カードを1回クリックするだけで、すべての関連コンテンツが表示されるようになった --- ### 4. ソートボタンの視覚的状態修正 **問題**: 「古い順」をクリックしても、見た目は「新しい順」が選択されたままに見える **原因**: `segmented-control` の `data-value` 属性が更新されていなかった **修正**: ```javascript // updateUI() 関数内に追加 document.querySelectorAll('.segmented-control').forEach(control => { control.setAttribute('data-value', currentSort); }); ``` **CSS仕様**: ```css .segmented-control[data-value="oldest"] .segmented-control-slider { transform: translateX(100%); } ``` **結果**: ソートボタンの視覚的状態が実際の状態と一致するようになった --- ### 5. ノートへのハッシュリンク実装(保留中) **目的**: 関連ノートのリンクをクリックしたら、ページ遷移せずに該当ノートまでスクロール **実装内容**: #### ノートカードに `data-slug` 属性を追加 ```html <div class="article-card" data-slug={note.slug}> ``` #### 関連ノートのリンクをハッシュ形式に変更 ```html <a href={`#note/${note.slug}`}> 📝 {note.data.title} </a> ``` #### ハッシュ変更を検知するJavaScript ```javascript function handleHashChange() { const hash = window.location.hash; const match = hash.match(/^#note\/(.+)$/); if (!match) return; const slug = match[1]; // ノートタブに切り替え currentMode = 'notes'; updateUI(); // カードを探して展開・スクロール const noteCard = document.querySelector(`[data-slug="${slug}"]`); if (noteCard) { noteCard.classList.add('expanded'); noteCard.scrollIntoView({ behavior: 'smooth', block: 'center' }); } } window.addEventListener('hashchange', handleHashChange); window.addEventListener('DOMContentLoaded', handleHashChange); ``` **問題**: URLは変わるが、該当ノートが表示されない(slugのマッチングがズレている?) **デバッグログ追加**: ```javascript console.log('Hash changed:', hash); console.log('Looking for note with slug:', slug); console.log('Found note card:', noteCard); console.log('Available note slugs:', Array.from(allNoteCards).map(...)); ``` **状態**: デバッグ中・保留 --- ### 6. プレビュー機能のアイデア検討 **要望**: 関連コンテンツのリンクにカーソルを合わせたら、カードがポップアップで表示されると便利 **課題**: スマホではカーソルがないため、別のアプローチが必要 #### 検討した実装案 ##### 案1: 長押し(Long Press)でプレビュー **操作**: - PC: ホバーでプレビュー - スマホ: 長押しでプレビュー、離すと消える **メリット**: - ✅ 誤タップを防げる - ✅ iOS Safari のリンクプレビューと同じ操作感 **デメリット**: - ❌ 長押しを知らないユーザーには分かりにくい ##### 案2: タップでプレビュー、もう一度タップで遷移 **操作**: - 1回目のタップ: プレビュー表示 - 2回目のタップ: リンク先へ - 外側タップ: プレビューを閉じる **メリット**: - ✅ 分かりやすい - ✅ PC でもクリックで同じ動作にできる **デメリット**: - ❌ 2回タップが必要 - ❌ 「すぐリンク先に行きたい」人には不便 ##### 案3: プレビューボタンを追加 **表示**: `📝 ノートタイトル [👁️]` **操作**: - タイトルクリック: そのまま遷移 - 👁️アイコンクリック: プレビュー表示 **メリット**: - ✅ 直感的 - ✅ プレビューしたい人だけ使える - ✅ PC/スマホで同じ操作 **デメリット**: - ❌ UI がやや複雑 - ❌ アイコン分のスペースが必要 ##### 案4: ボトムシート(推奨) **操作**: - PC: ホバーで小さなポップアップ - スマホ: タップで画面下からスライドアップ ``` スマホ画面 ┌──────────────┐ │ メインコンテ │ ├──────────────┤ ← スライドアップ │ プレビュー │ │ [閉じる] [開く]│ └──────────────┘ ``` **メリット**: - ✅ スマホで見やすい - ✅ PC/スマホで異なる最適なUIを提供 - ✅ 誤タップでも簡単に閉じられる **デメリット**: - ❌ 実装がやや複雑 #### 推奨アプローチ **案2(タップでプレビュー)+ 案4(ボトムシート)の組み合わせ** ```javascript // PC: ホバーで小さなツールチップ // スマホ: タップでボトムシート // 外側クリック/タップで閉じる // プレビュー内の「開く」ボタンで遷移 ``` **理由**: - PC とスマホで最適なUIを提供 - プレビュー不要な人は既存の動作(直接リンクタップ) - プレビュー欲しい人は関連コンテンツのリンクをタップ **状態**: アイデア段階・実装は未着手 --- ## 実装したファイル ### 変更ファイル 1. **web/src/pages/index.astro** - メインページ - HTMLの構造変更(glossary-card → article-card) - CSS追加(glossary-details の表示制御) - JavaScript修正(ソート状態更新、ハッシュナビゲーション) 2. **web/src/content/articles/** - 記事ファイルのfrontmatter修正 - `Obsidian Tips/` 配下53ファイル(topic重複削除) - `その他/振り返り/250714_📅KS250714_長い時間の練習は...md`(topic重複削除) - `Obsidian Tips/ks.220506_💎ローカルの汎用ファイルを扱うことのメリット.md`(title追加) --- ## 学んだこと ### 統一UIパターンの重要性 すべてのコンテンツタイプ(videos, articles, topics, notes)で同じUIパターンを使うことで: - ユーザーの学習コストが下がる - コードの保守性が向上する - 新機能(すべて開く/閉じるボタンなど)が全体に適用しやすい ### YAMLフロントマターのバリデーション - `topic` フィールドが2回定義されるとビルドエラーになる - Astro の Content Collections は Zod でスキーマ検証するため、必須フィールドが欠けているとエラー - ビルド前にローカルで `npm run build` を実行して、事前にエラーを検出すべき ### セグメントコントロールの状態管理 CSS だけでスライダー位置を制御する場合、JavaScript で `data-value` 属性を明示的に更新する必要がある: ```css .segmented-control[data-value="oldest"] .segmented-control-slider { transform: translateX(100%); } ``` ### ハッシュリンクの実装課題 - URL のハッシュは変わるが、`querySelector` でカードが見つからない問題 - `note.slug` の実際の値と、生成されるリンクの slug が一致していない可能性 - デバッグログで実際の値を確認する必要がある ### スマホとPCの異なるインタラクション プレビュー機能のような「ホバー」前提の機能は、スマホでは以下の選択肢がある: - 長押し(iOS風) - タップでプレビュー - ボタン追加 - ボトムシート → デバイスごとに最適なUIを提供するのが理想 --- ## 次のステップ ### 優先度高 1. **ノートへのハッシュリンク問題の解決** - コンソールログで slug の実際の値を確認 - `note.slug` と生成されるリンクが一致しているか検証 - マッチングが失敗する原因を特定 2. **プレビュー機能の実装** - PC: ホバーでツールチップ - スマホ: タップでボトムシート - まずは1つのコンテンツタイプ(ノートなど)で試作 ### 優先度中 3. **関連コンテンツの表示順序の最適化** - 現在: すべて時系列(新しい順) - 検討: 関連度や重要度で上位に持ってくるロジック 4. **ノートの本文プレビュー生成** - 現在: ノートは `description` が空の場合が多い - 検討: 本文の最初の100-150文字を自動抽出 ### 優先度低 5. **topics, articles, videos にもハッシュリンク拡張** - `#topic/slug`, `#article/slug`, `#video/slug` - すべてのコンテンツタイプで統一された URL 体系 6. **用語集ページの個別URL作成** - `/topic/[slug].astro` の実装 - SEO 最適化 --- ## 備考 - dev サーバー: `http://localhost:4321/` - ビルド: `npm run build` で警告のみ(dataview/srt/base 言語の Shiki 未対応) - ハッシュリンクのデバッグログは残したまま(次回セッションで使用)