fix: prevent scroll position jump when user scrolls up during content updates#28405
fix: prevent scroll position jump when user scrolls up during content updates#28405PiedPiper911 wants to merge 2 commits into
Conversation
|
Thanks for your pull request! It looks like this may be your first contribution to a Google open source project. Before we can look at your pull request, you'll need to sign a Contributor License Agreement (CLA). View this failed invocation of the CLA check for more information. For the most up to date status, view the checks section at the bottom of the pull request. |
Summary of ChangesHello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed! This pull request addresses an issue where the virtualized list component would incorrectly force a scroll-to-bottom behavior during content updates. By refining the condition that triggers the auto-scroll state, the component now correctly respects the user's current scroll position, ensuring a smoother experience when reviewing terminal output or agent responses. Highlights
Using Gemini Code AssistThe full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips. Invoking Gemini You can request assistance from Gemini at any point by creating a comment using either
Customization To customize the Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a Limitations & Feedback Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counterproductive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for GitHub and other Google products, sign up here. Footnotes
|
|
📊 PR Size: size/XS
|
There was a problem hiding this comment.
Code Review
This pull request modifies the scroll-sticking logic in VirtualizedList.tsx to prevent the scroll position from jumping to the bottom when new content arrives. However, the reviewer identified a logical issue where wasScrolledToBottomPixels evaluates to true when the content fits the container, which would cause unintended scroll jumps. A code suggestion was provided to explicitly check that the content did not previously fit.
| // Only re-enable isStickingToBottom when the user is genuinely at the | ||
| // bottom (not just when content previously fit). This prevents the scroll | ||
| // from jumping back to the bottom when the user has scrolled up to review | ||
| // changes (e.g., after Ctrl+S) and new content arrives. (#5009) | ||
| if (wasScrolledToBottomPixels && actualScrollTop >= prevScrollTop.current) { |
There was a problem hiding this comment.
There is a subtle logical issue with using wasScrolledToBottomPixels directly here.
When the content fits within the container (prevTotalHeight.current <= prevContainerHeight.current), prevTotalHeight.current - prevContainerHeight.current - 1 becomes a negative number (e.g., -1 or less). Since prevScrollTop.current is always >= 0 (or at least >= prevTotalHeight.current - prevContainerHeight.current), the condition prevScrollTop.current >= prevTotalHeight.current - prevContainerHeight.current - 1 will always evaluate to true.
This means wasScrolledToBottomPixels is always true when the content previously fit. As a result, if the user scrolled up while the content fit (which sets isStickingToBottom to false), the moment new content arrives and causes an overflow, wasScrolledToBottomPixels and actualScrollTop >= prevScrollTop.current will both be true, incorrectly re-enabling isStickingToBottom and causing the scroll position to jump to the bottom anyway.
To fix this, we should explicitly ensure that the content did not previously fit (i.e., !contentPreviouslyFit) when re-enabling isStickingToBottom based on wasScrolledToBottomPixels.
| // Only re-enable isStickingToBottom when the user is genuinely at the | |
| // bottom (not just when content previously fit). This prevents the scroll | |
| // from jumping back to the bottom when the user has scrolled up to review | |
| // changes (e.g., after Ctrl+S) and new content arrives. (#5009) | |
| if (wasScrolledToBottomPixels && actualScrollTop >= prevScrollTop.current) { | |
| // Only re-enable isStickingToBottom when the user is genuinely at the | |
| // bottom (not just when content previously fit). This prevents the scroll | |
| // from jumping back to the bottom when the user has scrolled up to review | |
| // changes (e.g., after Ctrl+S) and new content arrives. (#5009) | |
| if (!contentPreviouslyFit && wasScrolledToBottomPixels && actualScrollTop >= prevScrollTop.current) { |
There was a problem hiding this comment.
Great catch! You are right — when content fits within the container, wasScrolledToBottomPixels is always true because the threshold goes negative. I have adopted your suggestion and added the !contentPreviouslyFit guard to the condition. The updated check now reads:
if (!contentPreviouslyFit && wasScrolledToBottomPixels && actualScrollTop >= prevScrollTop.current)This ensures we only stick to the bottom when there was actual scrollable content and the user was at the bottom. Thanks for the precise analysis!
…ent fits When content fits within the container, wasScrolledToBottomPixels evaluates to true (threshold goes negative). Adding !contentPreviouslyFit explicitly prevents re-enabling isStickingToBottom in that edge case. Addresses review feedback from gemini-code-assist.
Summary
Fixes #5009 — scroll position jumps to top/bottom when user scrolls up to review changes (e.g., after Ctrl+S) and new content arrives.
Root Cause
In
VirtualizedList.tsx, theuseLayoutEffectthat manages auto-scroll has a condition that re-enablesisStickingToBottomtoo aggressively:The
wasAtBottomvariable includescontentPreviouslyFit, which istruewhen content fit in the container on the previous render. When new content arrives and causes the first overflow,contentPreviouslyFitis stilltruefrom the previous render — even if the user has explicitly scrolled up. This causesisStickingToBottomto be re-enabled, snapping the scroll toNumber.MAX_SAFE_INTEGER(the bottom).This manifests as the scroll "jumping to top" (actually jumping to bottom, then the terminal re-renders from top) when:
isStickingToBottomis incorrectly re-enabled → scroll jumpsFix
Change the condition for re-enabling
isStickingToBottomfromwasAtBottomtowasScrolledToBottomPixels. This ensuresisStickingToBottomis only re-enabled when the user's scroll position is genuinely at the bottom, not just when content previously fit.The auto-scroll-to-bottom logic (lines 371-388) still uses
wasAtBottomfor deciding whether to scroll to the new bottom when the list grows. This is correct — we want to auto-scroll when the user was at the bottom. The fix only affects theisStickingToBottomflag re-enablement.Changes
packages/cli/src/ui/components/shared/VirtualizedList.tsxisStickingToBottomfromwasAtBottomtowasScrolledToBottomPixels(1 line + comment)Test plan
Closes #5009