diff --git a/claude-notes/plans/2026-08-14-toc-location.md b/claude-notes/plans/2026-08-14-toc-location.md new file mode 100644 index 000000000..22777a31c --- /dev/null +++ b/claude-notes/plans/2026-08-14-toc-location.md @@ -0,0 +1,304 @@ +# toc-location option (left/right/body); unlocks banner toc-left class (bd-e2kpwy7n) + +**Date:** 2026-08-14 +**Braid:** bd-e2kpwy7n +**Branch:** investigated on `main` (worktree `.worktrees/bd-nn2fou8h-execute-visibility`, reused after its strand merged) +**Status:** Implemented 2026-08-14 on branch `braid/bd-e2kpwy7n-toc-location` (phases 0-4 complete; full `cargo xtask verify` passed 2026-08-14, all 14 steps including hub/WASM legs). Awaiting push approval. + +User-stated scope note: `external-sources/quarto-cli` is context, not a +contract — what matters is a mechanism that renders TOCs in alternative +locations (`left` first among them), not byte-for-byte Q1 parity. + +## Design decisions (user-aligned, 2026-08-14) + +1. **Value scope:** implement `left`, `right`, `body` now. `left-body` / + `right-body` warn-and-fall-back (`left-body` → `left`, `right-body` → + `right`) with a diagnostic; the clone behavior is a follow-up strand. +2. **Two mechanisms, Q1 parity:** port both `left` layouts — standalone + (`#quarto-sidebar-toc-left` + `.page-columns.toc-left` grid) and website + (TOC merged into `nav#quarto-sidebar`, `body.floating` grid). Possible + unification is a future cleanup, not this strand. +3. **Website merge lives in `SidebarRenderTransform`** (option (a)): the + rendered sidebar fragment contains the TOC, so custom templates that + emit `$rendered.navigation.sidebar$` keep working with no new + variables. Cost: `TocRenderTransform` must run before + `SidebarRenderTransform` (both Navigation-phase — reorder is legal), + and SidebarRender grows a synthesize-floating-sidebar branch for + website + left + no configured sidebar. +4. **`body` ships the decorated markup** (`nav-link`, + `data-scroll-target`, `.toc-active`) — deviation from Q1's plain list, + deliberate: scroll-spying is likely coming and the classes are inert + without the sidebar JS. +5. **No empty right-margin shell:** when the TOC moves left, q2 keeps + omitting `#quarto-margin-sidebar` entirely (deviation from Q1's empty + `zindex-bottom` shell — Q1's text-centric infra makes elision hard; we + can do better). +6. **Banner gate:** `banner-header-class: toc-left` when the (normalized) + location is exactly `left`. The `left-body` question is recorded on the + `*-body` follow-up strand (when it lands, the gate should cover + `left-body` too, fixing Q1's latent inconsistency). +7. **Preview parity is a follow-up strand** — `q2 preview`'s `TocSlot` + keeps showing the TOC on the right until that strand lands; flagged + there explicitly. + +Follow-up strands filed from this design: see "Follow-up strands" below. + +## Triage verdict + +**Ready to design.** (Superseded: design questions answered above; now +ready to implement.) The gap is confirmed at HEAD, the Q1 mechanism is +fully mapped, the q2 insertion points are identified, and the SCSS + +template hooks are already ported and inert. + +## Issue context + +Q2 has no `toc-location` option — the TOC always renders in the right margin +sidebar (`#quarto-margin-sidebar`). Filed 2026-07-17 as a P2 feature, +follow-up from the title-block parity epic (the banner `toc-left` +header-class hook was ported inert). On 2026-08-14 it gained real-world +impact data from the Posit Connect docs port: `api/index.html` is a 1.8 MB +OpenAPI reference whose only navigation is a 201-entry TOC with +`toc-location: left` — the port's worst page in chrome comparisons, and the +only page site-wide where Q1 emits `#quarto-sidebar` and q2 emits none. + +Committed minimal repro (external): +`/Users/cscheid/repos/github/cscheid/q2-connect-docs/llms-info/repros/toc-location-left/` +(re-verified unimplemented at 0.19.0/0.20.0/0.21.0 and HEAD `3ac596e0`). +Local copy of the same fixture: +`claude-notes/plans/toc-location-investigation/repro/`. + +## Dependency graph + +- **discovered-from**: bd-y71ga2l8 (closed) — title-block parity Phase 7 + (docs + follow-up strands). The title-block work ported the banner + `banner-header-class` template hook verbatim but left it inert because + its only Q1 producer derives `toc-left` from `toc-location`, which q2 + lacked. This strand is the missing producer. +- No incoming `blocks` edges; no children. Priority pressure comes from the + Connect-docs port (origin strand br-toc-location-left-q7hl5jgj in that + repo's skein), not from the q2 graph. + +## What the code looks like today + +The file references in the strand are current at HEAD: + +- `crates/quarto-core/src/template.rs:213-235` — `FULL_HTML_TEMPLATE` + hardcodes the TOC into `