Skip to content

脚注参照のホバー/フォーカスで内容をツールチップ表示する機能を追加#676

Open
cm-igarashi-ryosuke wants to merge 15 commits into
canaryfrom
feature/footnote-tooltip
Open

脚注参照のホバー/フォーカスで内容をツールチップ表示する機能を追加#676
cm-igarashi-ryosuke wants to merge 15 commits into
canaryfrom
feature/footnote-tooltip

Conversation

@cm-igarashi-ryosuke

@cm-igarashi-ryosuke cm-igarashi-ryosuke commented Jun 12, 2026

Copy link
Copy Markdown
Member

概要

本文中の脚注参照リンク([1] など)にホバーまたはキーボードフォーカスすると、脚注の内容をポップアップ(ツールチップ)で表示します。読者がページ末尾へジャンプせずに脚注を確認できるようにするものです(Wikipedia / GitHub と同等の UX)。

実装方式

document へのイベントデリゲーション + ページに 1 つの共有ツールチップ要素(遅延生成)。zenn-markdown-html の HTML 出力は変更しないため、変換済み・保存済みの既存記事にも JS の更新だけで適用されます(プログレッシブエンハンスメント)。

変更内容

zenn-embed-elements

  • src/classes/footnote-tooltip.ts(新規): ツールチップ本体
    • ホバー 150ms 後に表示 / ref とツールチップ両方から離れて 300ms 後に非表示(この猶予で内部リンクをクリック可能)
    • キーボードフォーカスで即時表示・Esc で閉じる・aria-describedby 付与(WAI-ARIA tooltip パターン)
    • タッチのみのデバイスでは matchMedia('(hover: hover)') 判定により無効(従来のジャンプ動作を維持)
    • 埋め込み要素(.embed-block)はクローンでは機能しない(iframe の高さ設定が listen-embed-event.js の id 照合に依存)ため、リンクに置換: data-content が URL のもの(linkcard / tweet / github / gist)は元 URL のテキストリンク、それ以外(YouTube / mermaid 等)は脚注へのアンカー
    • 画面端での位置反転・クランプ(自前の簡易ロジック、外部ライブラリなし)
  • vitest + jsdom のテスト基盤を新規導入し、ユニットテスト 21 件を追加
  • tsconfig.json の include を src/ に限定(テストが tsc ビルドに混入しないように)

zenn-content-css

  • src/_footnote-tooltip.scss(新規): ツールチップのスタイル。ルート要素に znc クラスを併用するため、CSS 変数によるダークモード追従と既存コンテンツスタイルの継承が自動で効きます

zenn-cli

  • articles/102-example-footnotes.md(新規): 動作確認用のサンプル記事(各種脚注パターン)

テスト

  • ユニットテスト 21 件(表示 / 非表示 / フォーカス / ガード条件 / 埋め込み置換)すべてパス
  • lint-strictbuild 通過、zenn-markdown-html のスナップショットテスト 217 件に影響なし(HTML 出力不変)
  • zenn-cli プレビューでの手動確認済み(ホバー表示・リンククリック・Esc・フォーカス・位置反転・ダーク/ライト両モード)

動作確認方法

cd packages/zenn-cli && pnpm dev

記事「脚注のテスト」(102-example-footnotes.md)を開き、各 [n] にホバー / Tab フォーカスしてください。

zenn.dev へ取り込む際の注意

  • ツールチップの z-index: 9999 と zenn.dev 本体のヘッダー等との重なりは本体側で要確認
  • 記事 HTML の再変換は不要(JS / CSS の更新のみで全記事に有効)

🤖 Generated with Claude Code


2026-06-12.10.50.07.mov

Comment thread packages/zenn-embed-elements/src/classes/footnote-tooltip.ts Dismissed
cm-igarashi-ryosuke and others added 14 commits June 12, 2026 09:50
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

本文中の脚注参照リンク(sup.footnote-ref > a)に対して、ホバー/キーボードフォーカス時に脚注内容を共有ツールチップ要素で表示する機能を追加するPRです。zenn-markdown-html のHTML出力を変えずに、JS/CSS更新のみで既存記事にも適用できる構成になっています。

Changes:

  • zenn-embed-elements にイベントデリゲーション方式の脚注ツールチップ実装を追加し、index.ts から初期化
  • zenn-content-css にツールチップのスタイルを追加し、既存 .znc のスタイル継承前提で適用
  • zenn-embed-elements に Vitest + JSDOM のテスト基盤とユニットテストを追加(サンプル記事も追加)

Reviewed changes

Copilot reviewed 9 out of 10 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
pnpm-lock.yaml jsdom/vitest 追加に伴う依存関係ロック更新
packages/zenn-embed-elements/vitest.config.ts Vitest 設定(jsdom環境・テスト探索範囲)を追加
packages/zenn-embed-elements/tsconfig.json tsc の include を src/ 配下に限定し、テスト等をビルド対象外に
packages/zenn-embed-elements/src/index.ts 脚注ツールチップ初期化を追加
packages/zenn-embed-elements/src/classes/footnote-tooltip.ts ツールチップ本体(表示/非表示・フォーカス対応・埋め込み置換・位置決め)を新規追加
packages/zenn-embed-elements/package.json vitest run のテストスクリプトと devDependencies(vitest/jsdom)を追加
packages/zenn-embed-elements/tests/footnote-tooltip.test.ts ツールチップ挙動のユニットテストを追加
packages/zenn-content-css/src/index.scss ツールチップスタイルの mixin を読み込み・適用
packages/zenn-content-css/src/_footnote-tooltip.scss ツールチップの見た目(最大幅/高さ、スクロール、色変数など)を追加
packages/zenn-cli/articles/102-example-footnotes.md 動作確認用のサンプル記事を追加
Files not reviewed (1)
  • pnpm-lock.yaml: Generated file

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +90 to +93
const id = decodeURIComponent(ref.hash.slice(1));
if (!id) return null;
const item = document.getElementById(id);
if (!item || !item.classList.contains('footnote-item')) return null;

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

対応済み

Comment on lines +119 to +123
let top = refRect.top - tipRect.height - margin;
if (top < margin) {
top = refRect.bottom + margin;
}

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

対応済み

レビュー指摘対応:
- decodeURIComponent が不正なパーセントエンコードで throw しないよう try/catch を追加
- 上下どちらにも収まらない場合にビューポート下端からはみ出さないよう top をクランプ

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 9 out of 10 changed files in this pull request and generated 3 comments.

Files not reviewed (1)
  • pnpm-lock.yaml: Generated file

Comment on lines +30 to +33
// znc クラスを付けることで CSS 変数とコンテンツスタイルを継承する
tooltip.className = 'znc zenn-footnote-tooltip';
tooltip.setAttribute('role', 'tooltip');
tooltip.hidden = true;
Comment on lines 33 to +39
"eslint": "^10.0.0",
"eslint-config-prettier": "^10.1.8",
"jsdom": "^29.1.1",
"rimraf": "^6.0.1",
"typescript": "^5.9.3",
"typescript-eslint": "^8.46.2"
"typescript-eslint": "^8.46.2",
"vitest": "^4.0.6"
Comment on lines 15 to 29
"scripts": {
"clean": "rimraf lib",
"build": "pnpm clean && run-p build:*",
"build:tsc": "tsc -p .",
"lint": "run-s lint:*",
"lint:eslint": "eslint .",
"lint:prettier": "prettier .",
"lint-strict": "run-s lint-strict:*",
"lint-strict:eslint": "eslint . --max-warnings 0",
"lint-strict:prettier": "prettier --check .",
"fix": "run-s fix:*",
"fix:eslint": "eslint . --fix",
"fix:prettier": "prettier -w .",
"test": "echo 'no test yet'"
"test": "vitest run"
},
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

feature 機能追加・改善

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants