Skip to content

fix(docs): heading anchor links now include the hash so it doesnt scoll all the way up, follows navbar logic#5791

Merged
colinhacks merged 1 commit into
colinhacks:mainfrom
FucciUnavailable:fix/heading-anchor-scroll
Apr 30, 2026
Merged

fix(docs): heading anchor links now include the hash so it doesnt scoll all the way up, follows navbar logic#5791
colinhacks merged 1 commit into
colinhacks:mainfrom
FucciUnavailable:fix/heading-anchor-scroll

Conversation

@FucciUnavailable

Copy link
Copy Markdown
Contributor

Fixes #5788

Problem

Clicking a heading (e.g. "Coercion") on a docs page like /api sets the
URL to ?id=coercion. Clicking the same heading a second time causes the
page to jump to the top instead of staying at the section.

This happens because the <Link> only sets a query param (?id=coercion).
When the URL hasn't changed, Next.js treats it as a no-op navigation —
no scroll happens, and the page snaps to top via scroll restoration.

The right-side TOC nav already uses ?id=coercion#coercion (both query
param and hash), which works reliably on every click.

Fix

Add the hash to the heading anchor href to match what the TOC nav already does:

  • Before: ?id=${props.id}
  • After: ?id=${props.id}#${props.id}

This means every click is always a real URL change (the hash is always
present), and the browser's native anchor scrolling handles positioning
correctly and idempotently.

@colinhacks

Copy link
Copy Markdown
Owner

@pullfrog review

@colinhacks colinhacks closed this Apr 28, 2026
@colinhacks colinhacks reopened this Apr 28, 2026

@pullfrog pullfrog Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Important

The one-line href fix is correct, but the PR also introduces an indentation regression on the commented-out code block (8 → 6 spaces). Ideally, all the dead commented-out code in this file should just be removed rather than reformatted.

Task list (5/5 completed)
  • Read the PR diff
  • Read the changed file in full for context
  • Check the linked issue #5788
  • Verify the fix matches existing TOC nav pattern
  • Submit review

Pullfrog  | Fix all ➔Fix 👍s ➔View workflow run | Using Claude Opus𝕏

data-card=""
// href={`#${props.id}`}
href={`?id=${props.id}`}
href={`?id=${props.id}#${props.id}`}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

The fix is correct — this matches the pattern used by the TOC nav and ensures every click is a real navigation event.

Comment on lines +25 to +38
// shallow={true}
// onClick={(e) => {
// // function __handleScroll(){
// // if id query parameter is present, scroll to the element with that id
// const params = new URLSearchParams(window.location.search);
// console.dir(params, { depth: null });
// const id = params.get("id");
// console.dir(params, { depth: null });
// if (id) {
// console.dir(document.getElementById(id), { depth: null });
// document.getElementById(id)?.scrollIntoView();
// }
// // }
// }}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

This block was indented at 8 spaces (aligned as <Link> props) and is now at 6. This is an unintentional formatting regression.

More broadly — this entire commented-out block (and the other stale comments on lines 21 and 23) are dead code that should be removed rather than carried forward. If you clean those up, the file becomes much simpler:

<Link
  data-card=""
  href={`?id=${props.id}#${props.id}`}
  className="peer"
>

@FucciUnavailable

Copy link
Copy Markdown
Contributor Author

I can get the indentation fixed!

@colinhacks

colinhacks commented Apr 28, 2026

Copy link
Copy Markdown
Owner

Thanks for the PR! Just wanted to flag that there's already a Scroller component (packages/docs/components/scroller.tsx) that handles this — it watches searchParams and calls scrollIntoView() on the element matching ?id=… whenever it changes. That's why the current ?id=foo href works on first click without a hash.

Going to close this out for now, but happy to revisit if there's a repro where the Scroller path isn't doing the right thing. Thanks again!

@colinhacks colinhacks closed this Apr 28, 2026
@FucciUnavailable

Copy link
Copy Markdown
Contributor Author

I appreciate your time reviewing this!

@colinhacks colinhacks reopened this Apr 30, 2026
@colinhacks

Copy link
Copy Markdown
Owner

Sorry, I understand the problem a little better now. Thanks for the PR!

@colinhacks
colinhacks merged commit 6fbe07b into colinhacks:main Apr 30, 2026
15 of 17 checks passed
@FucciUnavailable

Copy link
Copy Markdown
Contributor Author

I'm so glad!!
Thank you!! Excited to contribute more!!

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.

Buggy navigation on docs

2 participants