fix(diffs): keep scroll anchor stable when CodeView removes items - #1047
Conversation
Scroll partway down a CodeView list, then update the controlled items array to drop or reorder an earlier entry (for example, hiding an already-reviewed file). The viewport jumps to an unrelated position instead of staying on the item that was on screen. reconcileItems reassigns this.items without first capturing a scroll anchor, unlike setOptions, which always captures one before a layout-affecting change. Without a pending anchor, the next render's getScrollAnchor scans the old render window's indices against the freshly reindexed items array, reading position data that recomputeLayout has not refreshed yet, so the anchor it finds is wrong or nonexistent. Capture the anchor right before reassigning this.items, after the method's existing no-op early return rather than unconditionally at the top. A same-length update that changes nothing returns early without rendering, and render is what consumes a pending anchor; capturing before that check would leave a stale anchor on the instance for a later, unrelated render to "correct" against.
|
@fdarian is attempting to deploy a commit to the Pierre Computer Company Team on Vercel. A member of the Team first needs to authorize it. |
|
Hi! Yes, we should def fix this, but i think there's a few more areas of improvements. Your fix will only work if the top of your file is in the viewport so it can anchor to an earlier file. I'm take a few moments to try and see if i can get it to be more stable there and not cause a scroll jump if you're scrolled to the bottom of the file and remove it. (the reason it will break is because you'll capture a pending anchor for the deleted file, and then when it attempts to rectify it wont exist and everything will be broked, so i'm looking into a way to fix pending anchor capture to not include removed files) |
This updated implementation adds more robustness to scroll anchoring to continue to work on the following scenarios: * If the bottom of the item to be removed was visible in the viewport * Prevent anchoring to an element that will be removed * If the removed item took up the full viewport * Attempt to anchor to the next item's top
|
Oki, I added a commit that hardens this a bit more. So here's a before, that shows the existing fix, but also shows two other cases where the scroll anchoring breaks: bugs.mp4Basically if you delete an item who's bottom is fully in view, the scroll anchoring will break. And if you remove an item who takes up the FULL viewport, then you'll just be arbitrarily somewhere else. The fixes in action: fixed.mp4Added a way to ensure we never anchor to an element that will be removed in the next render (this fixes the visible bottom item breaking scroll anchoring). For items that fully take up the viewport, we just anchor the next item if it exists, to the top. |
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
@codex review |
|
Codex Review: Didn't find any major issues. 🚀 Reviewed commit: ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
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". |
Fixes a scroll-position bug in
CodeView's virtualized list: removing or reordering items in the controlleditemsarray destroys the user's scroll position instead of keeping their place.This one-line patch was discovered after Opus-5-observed Sonnet 5 did three iterations to solve the following bug. As shown in the video, removing an item will break the scroll position:
before.mp4
Then here's after it added the patch:
after.mp4
Type of changes
Checklist
moon run root:lint)moon run root:format)moonx diffs:test)Related issues
Possibly related to #1030, which is the same symptom (scroll anchor failing
to recover) via a different trigger (markdown remount / transient estimated
heights) and a different code path; not claiming this fixes it.