From 396200289e39c943d43aab42fb65128b5954e56f Mon Sep 17 00:00:00 2001 From: Shewart Date: Wed, 21 Oct 2026 15:56:17 +0200 Subject: [PATCH 1/4] fix(chrome): keep the table of contents working on interactive sites Under the circuit replaced the prerendered TOC and headings, so the scroll-spy watched detached elements and the highlight stopped moving. TOC links were bare #id, which resolves against to the home page. - TOC links carry the page's base-relative path (docs/setup#install) - the scroll-spy re-attaches when a render replaces the list or headings, or changes data-toc-ids on navigation - same-page links (#id in content too) scroll in place and keep the path - at the bottom of the page the last heading on screen is active --- docs/ARCHITECTURE.md | 2 +- .../Chrome/TableOfContents.razor | 10 ++- src/ShellDocs.Components/wwwroot/shelldocs.js | 66 ++++++++++++++++++- tests/ShellDocs.Tests/TableOfContentsTests.cs | 59 +++++++++++++++++ 4 files changed, 130 insertions(+), 7 deletions(-) create mode 100644 tests/ShellDocs.Tests/TableOfContentsTests.cs diff --git a/docs/ARCHITECTURE.md b/docs/ARCHITECTURE.md index eea92d5..62cf8ae 100644 --- a/docs/ARCHITECTURE.md +++ b/docs/ARCHITECTURE.md @@ -229,7 +229,7 @@ Chrome that must work without a Blazor runtime follows one contract: | Iframe previews | `[data-iframe-preview][data-src][data-lazy]` | sets the iframe's `src` (plus `?theme=`) when visible (IntersectionObserver), on `[data-iframe-run]` or at once; posts `{ type: "shelldocs-theme", theme }` to loaded frames on theme change; a host Blazor reuses for another page (`data-src` or `data-lazy` changed) is unloaded and set up again | | Mobile nav | page shell `[data-mobile-open]` | hamburger toggles; backdrop, Escape, link or navigation closes; page scroll locked on `` | | Sidebar collapse | page shell `[data-sidebar-collapsed]`, `[data-sidebar-collapse-toggle]` | toggles collapse; remembered in `localStorage` and restored as soon as `shelldocs.js` runs, so the sidebar doesn't flash open | -| TOC | `[data-toc-list][data-toc-ids]` | IntersectionObserver scroll-spy, re-attached on `enhancedload` | +| TOC | `[data-toc-list][data-toc-ids]`, `.toc-link` hrefs with the page path | IntersectionObserver scroll-spy (plus a scroll check for the page bottom), re-attached on `enhancedload` and when a render replaces the list or headings or changes `data-toc-ids`; same-page links (`#id` or the page's own path) are handled in a window capture listener: scroll, `replaceState` with the full path | | Search | `[data-search-dialog]` template, `[data-search-open]` | Cmd/Ctrl+K or a button opens a clone of the template; ranks `/_shelldocs/search.json`; arrows, Enter, Escape | | Theme | ``, `[data-theme-toggle]` | inline head script applies the saved / system theme; the toggle flips the class and CSS picks its icon; a `MutationObserver` saves any change (including another library's toggle) and pushes it to `ThemeState`; re-applied after enhanced navigation | diff --git a/src/ShellDocs.Components/Chrome/TableOfContents.razor b/src/ShellDocs.Components/Chrome/TableOfContents.razor index 58574b0..8f6dc77 100644 --- a/src/ShellDocs.Components/Chrome/TableOfContents.razor +++ b/src/ShellDocs.Components/Chrome/TableOfContents.razor @@ -1,9 +1,11 @@ @inject DocsPageState PageState +@inject NavigationManager Nav @implements IDisposable @using ShellDocs.Core -@* shelldocs.js attaches the scroll-spy from [data-toc-list] / [data-toc-ids]; - links are plain #anchors, so it works without a Blazor runtime. *@ +@* shelldocs.js attaches the scroll-spy from [data-toc-list] / [data-toc-ids] and + scrolls on click, so it works without a Blazor runtime. Links carry the page's + base-relative path: a bare #id resolves against to the home page. *@ @if (_items.Count > 0) {