Skip to content

Keep the docs sidebar mounted across navigation - #7868

Draft
masenf wants to merge 3 commits into
mainfrom
claude/sidebar-rerender-performance-56974c
Draft

masenf wants to merge 3 commits into
mainfrom
claude/sidebar-rerender-performance-56974c

Conversation

@masenf

@masenf masenf commented Nov 12, 2026 •

Copy link
Copy Markdown
Collaborator

Problem

Every docs page built its own copy of the desktop sidebar inside its route component. Each client-side navigation therefore unmounted it and mounted a fresh one, which:

  • reset the sidebar's scroll position (most noticeable when switching between package changelogs under API Reference)
  • collapsed any groups the reader had expanded
  • re-rendered the whole sidebar tree on every page change

Change

  • One persistent sidebar. The desktop sidebar is registered once as an app wrap (extra_app_wraps), outside the page routes, so navigation no longer unmounts it.
  • Reads the URL in the browser. The sidebar gets the current path from react-router's useLocation instead of from values computed per page in Python (calculate_index / normalize_url are removed). A group is open when the current route is one of its descendant pages.
  • Spacer slot. Each docpage reserves the column with an empty .docs-sidebar-slot. The shared sidebar is fixed-positioned over it, and a CSS :has rule hides it on pages without a slot (404, redirects).
  • Scrolls only when needed. If the active link is off-screen after navigating (prev/next, in-content links), the sidebar scrolls just enough to show it. This replaces the old on_mount script, which added a new popstate listener on every mount.
  • Truncated long labels (reflex-site-shared): a selected leaf such as reflex-components-react-player used to wrap past its fixed-height highlight. Leaf labels now truncate with an ellipsis, and the full name shows on hover.

Behavior notes

  • A group now opens whenever it contains the current page. The old index logic opened only the first match.
  • Groups a reader expands by hand stay open across navigation.
  • The mobile drawer still builds its own sidebar per page, which is fine since it closes on navigation.

Testing

  • New unit test for URL-driven group expansion; existing sidebar unit tests updated for the new signatures.
  • New browser tests: the sidebar keeps the same element and scroll offset across navigation, and a long active label stays on one line.
  • All 11 existing sidebar browser tests pass against a local dev server (built from a whitelisted subset of pages).
  • test_sidebar_offsets_follow_navbar_and_announcement failed once on a freshly compiled dev server and passed on every re-run. It looks like a pre-existing hydration race on the "Dismiss announcement" click, but I haven't checked it against main.

🤖 Generated with Claude Code

View guided diff Turn on auto-fix

Each docpage built its own copy of the desktop sidebar inside its route
component, so every client-side navigation unmounted it and lost the
scroll position and any groups the reader had expanded.

Render the sidebar once as an app wrap instead. It reads the current
route from react-router, opens a group when the route is one of its
descendant pages, and scrolls the active link into view only when it is
off-screen. Docpages reserve the column with an empty slot, and CSS hides
the shared sidebar on pages without one.

Also truncate long sidebar leaf labels so a selected item no longer wraps
past its fixed-height highlight; the full label shows on hover.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@greptile-apps

greptile-apps Bot commented Nov 12, 2026 •

Copy link
Copy Markdown
Contributor

RetriggerView in GreptileConfidence Score: 5/5

[Medium impact] The PR appears safe to merge; the numbered finding is fixed.

Summary

The desktop docs sidebar now stays mounted across navigation, preserving its scroll position and expanded groups.

  • The docs sidebar stays mounted while readers move between pages.
  • Long sidebar labels stay on one line and show their full text on hover.

Reviews (3) · Last reviewed commit: "Use rx.el.div for the docs sidebar wrapp..." · Reviewed by Greptile

@codspeed

codspeed Bot commented Nov 12, 2026 •

Copy link
Copy Markdown

Merging this PR will degrade performance by 2.1%

2 warnings

⚠️ 13 benchmarks are dominated by system calls

System calls cannot be simulated consistently and are left out of the measure. The reported value understates the real cost. Switch to the Walltime instrument to measure them.

Learn more about system calls

See affected benchmarks

⚠️ 4 benchmarks with a significant change ran on different hardware

Their base and head results were measured on machines with a different CPU, core count or memory, so the changes might not come from the code. Run base and head on the same runner type.

Learn more about Macro Runners

See affected benchmarks

⚡ 1 improved benchmark
❌ 3 regressed benchmarks
✅ 147 untouched benchmarks

Warning

Please fix the performance issues or acknowledge them on CodSpeed.

Performance Changes

Benchmark BASE HEAD Efficiency
❌ test_state_update_wire_serialization[model_1000] 25 ms 26.3 ms -4.96%
❌ test_route_matching[1000] 47.8 µs 50.2 µs -4.72%
❌ test_process_event_burst_independent_tokens[1] 2.7 ms 2.8 ms -4.21%
⚡ test_route_matching[100] 50.5 µs 47.7 µs +5.87%

Tip

Investigate this regression by commenting @codspeedbot fix this regression on this PR, or directly use the CodSpeed MCP with your agent.


Comparing claude/sidebar-rerender-performance-56974c (5e969b1) with main (a393487)

Open in CodSpeed

Groups derived their open prop from the live route, so React closed a
group the reader had expanded as soon as they navigated away from a page
inside it. Render each group's initial state from the route the sidebar
mounted on, which never changes afterwards, and have navigation open the
active link's ancestor groups directly instead. Navigation now only ever
opens groups, leaving the reader's own choices alone.

Also use rx.el.div for the sidebar column slot, per the docs app's
element conventions.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@FarhanAliRaza FarhanAliRaza added the bug Something isn't working label Nov 12, 2026 — with ChatGPT Codex Connector

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants