Skip to content

Persist sidebar scroll position across navigation#379

Open
AnnaXWang wants to merge 1 commit into
mainfrom
hypeship/persist-sidebar-scroll
Open

Persist sidebar scroll position across navigation#379
AnnaXWang wants to merge 1 commit into
mainfrom
hypeship/persist-sidebar-scroll

Conversation

@AnnaXWang
Copy link
Copy Markdown

@AnnaXWang AnnaXWang commented May 27, 2026

Summary

  • Adds sidebar-scroll.js at the repo root. Mintlify auto-injects any .js file in the content directory on every page.
  • The script saves the sidebar's scrollTop to sessionStorage whenever the user scrolls the sidebar or clicks a link inside it, and restores it after navigation (both SPA route changes via patched history.pushState/replaceState and full page loads).
  • Net effect: clicking an item deep in the sidebar no longer scrolls the menu back to the top — the next page renders with the sidebar still scrolled to where you were.

Why

Mintlify has no built-in setting to preserve sidebar scroll position. After clicking a nav link the sidebar resets to the top, so picking the page directly below the one you just visited requires re-scrolling.

Notes

  • Selector strategy is defensive (tries multiple sidebar candidates and picks the one that's actually scrollable) since Mintlify's DOM is not a stable contract.
  • If Mintlify ships a first-party fix, this file can be deleted.

Test plan

  • mintlify dev, open the API reference, scroll the sidebar down, click a deep link, confirm sidebar stays scrolled.
  • Verify on full reload (hard refresh on a deep page) the sidebar restores its position.
  • Confirm no console errors on initial load or navigation.

Note

Low Risk
Docs-only UX script with no auth, API, or data changes; main risk is brittle DOM selectors if Mintlify changes markup.

Overview
Adds a root-level sidebar-scroll.js script (intended for Mintlify to inject on every docs page) so the docs sidebar keeps its scroll position when users navigate.

On scroll (debounced) and on link clicks inside the sidebar, the script stores scrollTop in sessionStorage. After route changes it restores that offset by polling until the sidebar element exists, and it hooks history.pushState, history.replaceState, popstate, and load so both SPA navigations and full reloads get the same behavior.

Sidebar targeting is defensive: it picks the first matching aside / labeled nav / #sidebar element that is actually scrollable, since Mintlify’s DOM is not guaranteed stable.

Reviewed by Cursor Bugbot for commit 34326a0. Bugbot is set up for automated code reviews on this repo. Configure here.

@mintlify
Copy link
Copy Markdown
Contributor

mintlify Bot commented May 27, 2026

Preview deployment for your docs. Learn more about Mintlify Previews.

Project Status Preview Updated (UTC)
Kernel 🟢 Ready View Preview May 27, 2026, 3:39 AM

💡 Tip: Enable Workflows to automatically generate PRs for you.

@ehfeng ehfeng marked this pull request as ready for review May 27, 2026 05:29
@firetiger-agent
Copy link
Copy Markdown

Firetiger deploy monitoring skipped

This PR didn't match the auto-monitor filter configured on your GitHub connection:

Any PR that changes the kernel API. Monitor changes to API endpoints (packages/api/cmd/api/) and Temporal workflows (packages/api/lib/temporal) in the kernel repo

Reason: PR modifies documentation/UI behavior (sidebar scroll persistence) and does not change kernel API endpoints or Temporal workflows.

To monitor this PR anyway, reply with @firetiger monitor this.

Copy link
Copy Markdown

@cursor cursor Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 34326a0. Configure here.

Comment thread sidebar-scroll.js
if (isNaN(top)) return false;
if (Math.abs(sb.scrollTop - top) > 1) sb.scrollTop = top;
return true;
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Restore reports success prematurely

Medium Severity

After navigation, restore always returns success once a saved value exists and a sidebar node is found, even when scrollTop could not be set to the stored offset. pollRestore then stops retrying, so a sidebar that is not yet scrollable can stay at the top once content finishes laying out.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 34326a0. Configure here.

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 34326a0d46

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread sidebar-scroll.js
Comment on lines +7 to +9
var candidates = document.querySelectorAll(
"aside, nav[aria-label='Sidebar'], aside[aria-label='Sidebar'], #sidebar"
);
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Prefer the documented scrollable sidebar element

Mintlify documents #sidebar-content as the scrollable content area inside the sidebar, but this selector only considers the outer containers. On pages where the user actually scrolls #sidebar-content, save() records the outer #sidebar/aside scrollTop (typically 0) or finds nothing, so deep API/sidebar navigation still resets instead of restoring the position. Include and prefer #sidebar-content before the container selectors so the saved value comes from the element that receives the scroll.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown

@cursor cursor Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Risk assessment: Low.

This PR adds one Mintlify custom JavaScript file that runs globally on the docs site to persist sidebar scroll position. The change affects user-facing docs navigation behavior, so it is above very-low risk, but the blast radius is limited to docs UI state: it uses sessionStorage, DOM scroll listeners, and history event hooks only, with no backend, auth, billing, infrastructure, data model, or external network impact.

I found no CODEOWNERS file in this repo and the PR did not already have an approval, so I’m approving based on the low-risk classification.

Open in Web View Automation 

Sent by Cursor Automation: Assign PR reviewers

@ehfeng
Copy link
Copy Markdown
Contributor

ehfeng commented May 27, 2026

This seems fine, but would it be better just to have the sidebar scroll to the selected item? Feels simpler long term.

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.

2 participants