Skip to content

wip: scroll anchoring improvements for chat - #10600

Draft
yihuiliao wants to merge 9 commits into
mainfrom
reverse-virtualizer-follow-up
Draft

yihuiliao wants to merge 9 commits into
mainfrom
reverse-virtualizer-follow-up

Conversation

@yihuiliao

@yihuiliao yihuiliao commented Sep 11, 2026

Copy link
Copy Markdown
Member

This PR fixes a couple of things. Some of which were from testing in July and some that were noticed while making the ai component docs.

  1. Updates the width of the Chat in storybook so it fits on mobile screens
  2. Removes unneeded state to calculate scroll anchoring (see devon's comment)
  3. Fixes the scroll positioning from jumping on mobile
  4. Expanding and collapsing response status in virtualized chat thread has weird scroll behavior (like it is opening upward). Probably scroll anchoring related. Should open downwards.

For 2, I removed the hadEstimatedVisibleItems / wasNearAnchorEdge fields that tried to remember "are we near the edge?" across a resize. They were redundant since resolveScrollAdjustment already gets itemSizeChanged and contentSizeDelta per pass, so the same decision (follow edge vs. keep anchor) can be made directly from those without tracked history. Simpler and less prone to going stale.

For 3, scroll position jumped on mobile, there were two problems combined on small screens. First, we picked anchor candidates from this._visibleViews (only views already on screen, with a possibly stale layout as backup). Switched to this.getVisibleLayoutInfos(), which asks the layout directly for everything in view, giving a more accurate list to anchor to. Second, an item could only be anchored if it fit fully inside the viewport. On mobile, one tall item can fill the whole screen, so nothing ever fully fit and no anchor was picked. Now we anchor to the item closest to the edge even if it's partly cut off, falling back to the least-cut-off item if none fit.

For 4, expanding/collapsing response status scrolled upward instead of staying put, a resize anywhere in the list was treated as if it happened at the anchored edge when the chat was short, so the virtualizer would "follow the edge" and snap the scroll position, even when the resized item was in the middle of the list. Added tracking for whether a resize batch actually touched the newest item; if it didn't, we preserve the user's reading position instead of following the edge.

✅ Pull Request Checklist:

  • Included link to corresponding React Spectrum GitHub Issue.
  • Added/updated unit tests and storybook for this change (for new code or code which already has tests).
  • Filled out test instructions.
  • Updated documentation (if it already exists for this component).
  • Looked at the Accessibility Practices for this feature - Aria Practices
  • I understand every change in this PR and can explain why it's there.
  • If AI-assisted, I followed our AI contribution guidance and pointed my assistant at CLAUDE.md.

📝 Test Instructions:

🧢 Your Project:

@rspbot

rspbot commented Sep 11, 2026

Copy link
Copy Markdown

@rspbot

rspbot commented Sep 11, 2026

Copy link
Copy Markdown

Agent Skills Changes

Modified (9)
Install

React Spectrum S2:

npx skills add https://d1pzu54gtk2aed.cloudfront.net/pr/1fed441c0c8692d35b957e9be38339182c5f418e/

React Aria:

npx skills add https://d5iwopk28bdhl.cloudfront.net/pr/1fed441c0c8692d35b957e9be38339182c5f418e/

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants