Soft Navigation Into A Nested Layout Scrolls Past The New Layout To The Page
When navigating to a route that introduces a new nested layout, Next.js scrolls to the page segment instead of the top of the newly mounted layout, causing the layout's heading and intro content to be bypassed. This occurs because the scroll ref is only accumulated for leaf segments in render-tree.ts.
In createRenderTreeOnNavigation (render-tree.ts), the scroll ref is assigned only when `isLeafSegment` is true, i.e., for the leaf page segment. When a navigation introduces a new layout segment, that layout is the topmost new segment but is not a leaf, so its scroll ref is never used. The browser then scrolls to the page child, skipping the new layout content.
1. Clone https://github.com/stefanprobst/next-nested-layout-scroll-repro
2. Run `pnpm install && pnpm build && pnpm start`
3. Open http://localhost:3000/ in a viewport about 800px tall, scrolled to the top.
4. Click 'Section'.
5. Observe scrollY becomes 1040 instead of expected 0.
The patch adds a `hasScrollRef` flag to `ScrollAccumulation` and initializes it to `false` where the accumulation is created. In `createRenderTreeOnNavigation`, instead of only accumulating for leaf segments, we now accumulate for any new segment (`freshness > 0`) as long as no scroll ref has been set yet. The first new segment encountered is the topmost newly mounted layout or page; subsequent deeper segments are ignored because `hasScrollRef` becomes true. Thus the scroll target becomes the topmost new layout (if any), falling back to the page if only the page is new, matching expected behavior.
Edge Case Audit
This fix assumes the accumulation object is fresh per navigation request. If the same accumulation object is reused across multiple navigations without resetting `hasScrollRef`, the scroll ref from the first new segment might be retained incorrectly. Ensure `hasScrollRef` is reset for each new navigation. Concurrent or interrupted navigations could also expose state races if the accumulation is shared; the object should be scoped per render. Rollback is straightforward: revert this diff to restore the previous leaf-only behavior. Additional tests should cover nested layout transitions, sibling layouts (tabs), and deep links to verify no regression in existing scroll behavior.