Skip to content

fix: keep virtualized async ListBox focus visible#10165

Open
000vincent999 wants to merge 3 commits into
adobe:mainfrom
000vincent999:fix-10129-listbox-virtualized-end-key
Open

fix: keep virtualized async ListBox focus visible#10165
000vincent999 wants to merge 3 commits into
adobe:mainfrom
000vincent999:fix-10129-listbox-virtualized-end-key

Conversation

@000vincent999

Copy link
Copy Markdown

Closes #10129

Summary

This fixes keyboard navigation for virtualized async ListBox collections when pressing End or paging after more items have loaded.

Previously, focusedKey could move to the newest last item, but ListLayout did not always compute layout info for that focused/persisted key. The old fallback only forced a full layout when requestedRect.area < contentSize.area. Because the virtualizer overscans on both axes, a vertical list can get extra cross-axis width in requestedRect, making the area comparison look large enough even though the newly loaded focused item has not been laid out. As a result, the item was not mounted and could not be scrolled into view.

The fix makes ListLayout key-driven for this fallback: if a persisted key is missing from layoutNodes but exists in the current collection, it computes the full layout so the focused item can be rendered. This avoids relying on cross-axis-sensitive area comparisons. The change also refreshes the virtualizer visible rect after programmatic focus scrolling and re-scrolls virtualized collections when the collection object changes while the focused key remains the same.

✅ Pull Request Checklist:

  • Included link to corresponding React Spectrum GitHub Issue.
  • Added/updated unit tests and storybook for this change.
  • Filled out test instructions.
  • Updated documentation. Not applicable for this behavior-only bug fix.
  • Looked at the Accessibility Practices for this feature. This preserves the expected ListBox keyboard navigation behavior.

📝 Test Instructions:

  • yarn jest packages/react-stately/test/virtualizer/ListLayout.test.ts --runInBand
  • yarn vitest --config=vitest.browser.config.ts packages/react-aria-components/test/ListBox.browser.test.tsx

Local verification:

  • Passed: yarn jest packages/react-stately/test/virtualizer/ListLayout.test.ts --runInBand
  • Not completed locally: the browser test command requires Playwright browser binaries, and this environment reported missing Chromium/Firefox/WebKit executables. Run yarn playwright install before the browser test command.

🧢 Your Project:

Personal contribution

);
let refreshVisibleRectRef = useContext(RefreshVisibleRectContext);
if (refreshVisibleRectRef) {
refreshVisibleRectRef.current = refreshVisibleRect;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This breaks the rules of hooks, cannot read or write to a ref during render

@snowystinger snowystinger left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Thank you for the interest. This is a lot of very involved changes, maybe it'd be good to write up a more formal RFC for this to get comments on the direction. https://github.com/adobe/react-spectrum/blob/main/rfcs/template.md

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.

ListBox keyboard navigation with Virtualizer fails to focus and scroll to last item during async loading

3 participants