Skip to content

fix(docs): keep the sidebar pinned on click, and one scroll bar for every scroll region - #159

Merged
hunterbecton merged 4 commits into
mainfrom
hunter/sha-130-sidebar-scroll-position
Sep 9, 2026
Merged

fix(docs): keep the sidebar pinned on click, and one scroll bar for every scroll region#159
hunterbecton merged 4 commits into
mainfrom
hunter/sha-130-sidebar-scroll-position

Conversation

@hunterbecton

@hunterbecton hunterbecton commented Sep 8, 2026

Copy link
Copy Markdown
Contributor

Why

Scrolling the components sidebar to its last group and clicking a row opened the new page with the sidebar back at the top (SHA-130). While in there, every scroll bar on the site now matches the thin one the control panel draws.

What changes

The sidebar pins instead of dropping back under the banner

The nav survives navigation and keeps its inner scroll. What moves is the window. The sidebar is sticky under 200px of header and banner that scroll away, so a reader reaches its lower groups by scrolling the window until the nav pins, and Next's scroll-to-top on navigation drops it back down and pushes those groups below the fold. A Playwright probe showed the clicked row off screen at every viewport height below 1329px.

Sidebar rows now pass scroll={false}, and a click handler on the nav clamps the window to the shell's top before the router swaps the page. A reader who was past the banner lands with the sidebar exactly where it was and the new page's breadcrumbs, title, and demo at the top. A reader who was not sees nothing move. The clamp runs on click rather than after the route change so back and forward keep the browser's own scroll restoration.

One scroll bar for every scroll region

components/scroll-area wraps Base UI's Scroll Area and owns the bar and thumb styles the control panel had, plus a horizontal orientation. The control panel, the sidebar, the Usage and props-table code blocks, the guides' fenced code, the search results, and the guides' table of contents all scroll through it. Shiki's unconditional tabindex comes off its <pre>, because the viewport is already a tab stop whenever the code overflows. The window's own bar gets the same thumb through scrollbar-width and scrollbar-color on the root.

A Playwright spec for both sidebar paths

apps/docs-tests/docs/sidebar-scroll.spec.ts reproduces the bug at a 720px viewport and checks that a click from deep in a page still opens the new page at its top. Red before the fix, green after, and the a11y suite stays green.

Known limitations

When the reader was already past the banner, the new page opens with the banner scrolled off, which is what the page looked like before the click. Bringing the banner back would mean a sticky header, a design change rather than a bug fix.

🤖 Generated with Claude Code

The sidebar is sticky under a header and banner that scroll away, so a
reader reaches its lower groups by scrolling the window until the nav
pins. Next's scroll-to-top on navigation then dropped the nav back under
the banner and pushed those groups below the fold. Sidebar rows now opt
out of that scroll, and a click handler clamps the window to the shell's
top before the route changes, so the sidebar stays where it was and the
new page still opens at its breadcrumbs. A Playwright spec covers both
paths.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@github-actions

github-actions Bot commented Sep 8, 2026

Copy link
Copy Markdown
Contributor

React Doctor found no new issues. 🎉

Reviewed by React Doctor for commit f87296c.

@coderabbitai

coderabbitai Bot commented Sep 8, 2026

Copy link
Copy Markdown

Review Change StackReview Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Advanced

Run ID: d2812919-27f9-4bb1-b1df-affeea4952d5

📥 Commits

Reviewing files that changed from the base of the PR and between 366f40c and f87296c.

📒 Files selected for processing (1)
  • apps/docs/src/components/docs-sidebar/docs-sidebar.tsx

Limit details: You’ve used the included review currently available.


📝 Summary

Summary by CodeRabbit

  • New Features

    • Added consistent scroll areas to documentation sidebars, tables of contents, search results, controls, and code blocks.
    • Improved scrolling and rounded clipping for wide code examples.
    • Added matching window scrollbar styling across the documentation site.
  • Bug Fixes

    • Improved sidebar navigation so selected sections remain visible and destination pages open at the expected position.
    • Preserved standard behavior for modified clicks and non-navigation interactions.
  • Tests

    • Added coverage for sidebar scrolling, navigation, page positioning, and destination content visibility.

Walkthrough

Documentation scrolling now uses a shared ScrollArea component across navigation, search, table of contents, controls, and code blocks. Sidebar navigation preserves the sidebar position, and Playwright tests cover the resulting behavior.

Changes

Documentation scroll areas

Layer / File(s) Summary
Shared ScrollArea foundation
apps/docs/src/components/scroll-area/*
Adds shared vertical and horizontal scrolling primitives with configurable orientation, viewport classes, overlays, thresholds, and scrollbar styling.
Documentation scroll integrations
apps/docs/src/components/docs/TableOfContents.tsx, apps/docs/src/components/SearchBar.tsx, apps/docs/src/components/controls/*, apps/docs/src/app/globals.css
Moves the table of contents, search results, and demo controls to the shared ScrollArea component. Updates scrollbar and search viewport styles.
Horizontal code-block scrolling
apps/docs/src/content/mdx.tsx, apps/docs/src/components/code-block/*
Wraps code blocks in a horizontal ScrollArea, sizes <pre> elements to their content, clips rounded viewports, and removes Shiki-generated tabindex attributes.
Sidebar navigation and validation
apps/docs/src/components/docs-sidebar/*, apps/docs-tests/docs/sidebar-scroll.spec.ts
Attaches pinning behavior directly to sidebar rows, preserves navigation scroll position, and tests sidebar visibility, active-row state, destination URLs, and top-of-page rendering.

Priority: ➖ Normal

Estimated code review effort: 3 (Moderate) | ~20 minutes

Merge Risk: ⚪ Minimal · up to f8729

Documentation navigation now preserves the sidebar position and avoids unwanted page scroll resets, with coverage for navigation from scrolled states. No actionable merge-blocking risk is identified.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 42.86% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 14 functions across 8 files. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the two main changes: preserving the pinned docs sidebar on navigation and standardizing scrollbars across scroll regions.
Description check ✅ Passed The description directly explains the sidebar navigation fix, shared ScrollArea adoption, scrollbar styling, accessibility behavior, tests, and known limitation.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
  • Fix all pre-merge checks with AI
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch

Warning

Some tools did not complete. Review the errors below.

🔧 ESLint

If the error stems from missing dependencies, add them to the package.json file. For unrecoverable errors (e.g., due to private dependencies), disable the tool in the CodeRabbit configuration.

ESLint install failed. For unrecoverable errors, disable the tool in CodeRabbit configuration.

Usage-based review receipt

Note

This review was completed with usage-based billing: files reviewed beyond your plan's included limits are billed at $0.25/file. View usage-based billing.


Comment @coderabbitai help to get the list of available commands.

One shared ScrollArea now owns the thin fading bar the control panel
introduced, with a horizontal orientation for code. The docs sidebar,
the control panel, the Usage and props-table code blocks, the guides'
fenced code, the search results, and the guides' table of contents all
scroll through it. Shiki's unconditional tabindex comes off its <pre>,
since the viewport is already a tab stop whenever the code overflows.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@hunterbecton hunterbecton changed the title fix(docs): keep the sidebar pinned when a row is clicked fix(docs): keep the sidebar pinned on click, and one scroll bar for every scroll region Sep 8, 2026
hunterbecton and others added 2 commits September 8, 2026 20:11
scrollbar-width and scrollbar-color on the root give the page's own bar
the gray-600 thumb on a transparent track that the inner scroll areas
draw, so every bar on the site matches.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
React Doctor flagged the click handler on the nav as a handler on a
non-interactive element with no keyboard counterpart. Each row's Link
now carries it instead, which also drops the target checks the
delegation needed. Enter on a focused row fires a click event, so
keyboard readers get the same pin.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@hunterbecton
hunterbecton merged commit 8585f4a into main Sep 9, 2026
7 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant