diff --git a/ui/docs/report-view.md b/ui/docs/report-view.md index 6822ee7..a756157 100644 --- a/ui/docs/report-view.md +++ b/ui/docs/report-view.md @@ -85,8 +85,8 @@ the body — both surfaces stay in sync by construction. ## Table of contents and active highlight -`report/report-toc.svelte` renders a single sticky icon-popup -trigger in the top-right corner of the report column. The trigger +`report/report-toc.svelte` renders a single icon-popup trigger +pinned to the top-right corner of the report column. The trigger shows `≡` followed by the title of the currently-active section (CSS-clamped with `text-overflow: ellipsis` so a long RU title cannot bloat the button). Clicking opens an anchored popover @@ -97,8 +97,29 @@ the matching `
` into view via `scrollIntoView` (with `prefers-reduced-motion` falling back to `behavior: "auto"`). -On viewports below `768.98 px` the same surface re-styles into a -fixed bottom-sheet anchored above the layout-owned bottom-tabs +The trigger uses `position: fixed` instead of `position: sticky`. +Per the CSS sticky spec a sticky element sticks within its nearest +ancestor with non-`visible` overflow — and `.active-view-host` +declares `overflow-y: auto` for the mobile scroll story. On +desktop the host grows with content and the document body becomes +the actual scroll container, so a sticky trigger inside the report +column never receives a scroll event and rides up with the page +content. A fixed trigger sidesteps the chain entirely; the +component is mounted only while the report active view is on +screen, so the fixed element is naturally tied to the view's +lifetime. The desktop offset is `right: calc(18 rem + 1.25 rem)` +to clear the always-on `lib/sidebar/sidebar.svelte`; below +1024 px the sidebar collapses to an overlay drawer, so the +default `right: 1.25 rem` matches the report's right padding. The +report-view itself adds a top padding equal to the trigger's +viewport offset plus its height so the first section's heading +does not render under the trigger at scroll position 0, and every +`
` gets `scroll-margin-top: 7.5rem` so +`scrollIntoView({ block: "start" })` lands the heading below the +trigger after a popover-driven jump. + +On viewports below `768.98 px` the popover surface re-styles into +a fixed bottom-sheet anchored above the layout-owned bottom-tabs bar (mirrors `lib/active-view/map-toggles.svelte`), so the same trigger and the same menuitem list serve desktop and mobile. diff --git a/ui/frontend/src/lib/active-view/report.svelte b/ui/frontend/src/lib/active-view/report.svelte index 11330a7..e0f0392 100644 --- a/ui/frontend/src/lib/active-view/report.svelte +++ b/ui/frontend/src/lib/active-view/report.svelte @@ -134,10 +134,14 @@ TOC and the body iterate the same data. diff --git a/ui/frontend/src/lib/active-view/report/report-toc.svelte b/ui/frontend/src/lib/active-view/report/report-toc.svelte index e267cef..d147b64 100644 --- a/ui/frontend/src/lib/active-view/report/report-toc.svelte +++ b/ui/frontend/src/lib/active-view/report/report-toc.svelte @@ -143,14 +143,43 @@ in F8-09: that switch is available in the app-shell view menu.