Render Select options in chunks as the list scrolls#14663
Open
nessai1 wants to merge 1 commit into
Open
Conversation
Opening a Select with tens of thousands of options (e.g. picking a target branch in a repo with ~25k remote branches) rendered every option eagerly, freezing the UI for ~13s on open and making the search input unusable (~80s to type a query). Render the first 100 options and grow the window as the dropdown scrolls; reset the window when the search term changes. With the new 25k-option story, opening the dropdown drops from ~13.3s to ~80ms and search typing from ~80s to ~85ms. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Collaborator
|
Thanks a lot for giving this a go! As virtual/chunked rendering is inherently difficult to get right (also across browsers), especially when constants are involved, would you be able to provide before/after videos showing off the fix? Thanks again lot for your help! |
Author
|
Here are the before/after videos, recorded against a real repo with ~25k remote branches :) Before (master):
master.mp4release.mp4After (this branch), same repo, same builds:
fix.mp4 |
Collaborator
|
Thanks so much for bearing with me: These results are impressive and I see how much they're needed now. |
Contributor
|
Great contribution, thank you! I might still have a preference for moving |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
Selectrenders every filtered option eagerly. With a small option list that's fine, but the target-branch selector during project setup (ProjectSetupTarget.svelte) feeds it all remote branches of the repository. On a large monorepo clone (25,261 remote branches, ~600k commits) this means ~25k DOM nodes created in one shot when the dropdown opens — and re-created on every search keystroke.Measured on an M-series MacBook against a Storybook story with 25,000 options:
In the real app the freeze is long enough that onboarding a large repo looks like a hang.
Fix
Render options in chunks of 100:
renderedOptions = filteredOptions.slice(0, renderLimit)— grouping and keyboard navigation derive from the rendered window;onscrollhook ofScrollableContainer;No API changes; small lists (< 100 options) behave exactly as before. Since the component already has no scroll-into-view for keyboard highlight, chunking does not regress keyboard behavior: navigation cycles within the rendered window.
Repro / testing
Huge Liststory (25k options) toSelect.stories.svelte— open the dropdown before/after this change to feel the difference.svelte-checkandeslintpass on the touched files.To reproduce the original pain end-to-end: any repo with tens of thousands of remote branches (
git config remote.origin.fetch '+refs/heads/*:refs/remotes/origin/*'against a big shared monorepo does it) — then add the project in GitButler and open the target-branch dropdown.🤖 Generated with Claude Code