Skip to content

fix(web): Virtualize model picker#2929

Open
chanyeinthaw wants to merge 1 commit into
pingdotgg:mainfrom
chanyeinthaw:model-picker
Open

fix(web): Virtualize model picker#2929
chanyeinthaw wants to merge 1 commit into
pingdotgg:mainfrom
chanyeinthaw:model-picker

Conversation

@chanyeinthaw
Copy link
Copy Markdown

@chanyeinthaw chanyeinthaw commented Jun 3, 2026

What Changed

Virtualized the model picker list for large provider model inventories.

When the picker has more than 60 visible models, it now uses LegendList instead of rendering every model row at once. Smaller lists still use the existing non-virtualized ComboboxList path.

The virtualized path preserves the existing model picker behavior:

  • search still works
  • keyboard navigation still works
  • highlighted rows scroll into view
  • favorites still work
  • provider labels, badges, shortcuts, and row styling are unchanged

Why

OpenCode can expose very large model inventories. In my case, selecting OpenCode caused the picker to try rendering around 199 models into the UI at once.

Each row includes several relatively expensive pieces of UI: combobox item state, tooltip, favorite button, provider icon, shortcut label, model metadata, and badges. Rendering all of that eagerly made opening and interacting with the picker noticeably slow.

Virtualizing the list fixes the performance issue directly by only mounting the visible rows plus a small buffer. This keeps the picker responsive without changing the model data, search logic, or selection behavior.

UI Changes

The UI should look the same. This is a performance-focused interaction change.

Before: opening OpenCode’s model picker was slow because every model row rendered eagerly.

After: opening and searching the OpenCode model picker is much faster because only visible rows are rendered.

A short before/after interaction video would be useful here if available.

Checklist

  • This PR is small and focused
  • I explained what changed and why
  • I included before/after screenshots for any UI changes
  • I included a video for animation/interaction changes

Note

Low Risk
UI-only performance and styling changes in the model picker and popover; selection, search, and favorites logic are unchanged aside from list rendering strategy.

Overview
When the filtered model list has more than 60 entries, the picker switches from rendering every row to a LegendList virtual list inside ComboboxListVirtualized, with estimated row height and max height tuned for sidebar vs no-sidebar layouts. Smaller lists keep the existing ComboboxList path; the scroll-area measurement useLayoutEffect is skipped when virtualized.

Combobox is told virtualized={true} on the large-list path, and keyboard highlight calls scrollIndexIntoView on the list ref so arrow-key navigation still tracks off-screen items. Row rendering is centralized in renderModelRow; ModelListRow gains per-row border-b / isLast instead of list-level divide-y.

Minor chrome tweaks: the picker sidebar drops its right border, and the popover viewport uses rounded-b-[inherit] for bottom corner alignment.

Reviewed by Cursor Bugbot for commit 405e7d6. Bugbot is set up for automated code reviews on this repo. Configure here.

Note

Virtualize the model picker list for large model sets

  • Adds list virtualization to ModelPickerContent when more than 60 filtered models are present, constraining the list height and improving scroll performance.
  • Uses LegendList with a new ComboboxListVirtualized wrapper; keyboard-driven item highlighting calls scrollIndexIntoView to keep the focused row visible.
  • Moves row separator borders from list-level divide-y to per-row styling in ModelListRow via a new isLast prop.
  • Minor visual fixes: removes the sidebar's right border and adds rounded-b-[inherit] to the popover viewport.

Macroscope summarized 405e7d6.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Jun 3, 2026

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 0aad19e8-9abf-4735-bc29-6c8bf03f8621

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@chanyeinthaw chanyeinthaw changed the title Virtualize model picker, some UI adjustments to make it looks good Virtualize model picker Jun 3, 2026
@github-actions github-actions Bot added size:L 100-499 changed lines (additions + deletions). vouch:unvouched PR author is not yet trusted in the VOUCHED list. labels Jun 3, 2026
Copy link
Copy Markdown
Contributor

@cursor cursor Bot left a comment

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit b22f0f9. Configure here.

index: eventDetails.index,
animated: false,
});
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Virtual list scroll not reset

Medium Severity

With virtualization enabled, the LegendList keeps its scroll offset when filteredModelKeys changes (search or sidebar), but there is no scroll-to-top like the branch picker. scrollIndexIntoView runs only for keyboard highlights, so after filtering the highlighted row can stay off-screen while the viewport shows unrelated models.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit b22f0f9. Configure here.

@macroscopeapp
Copy link
Copy Markdown
Contributor

macroscopeapp Bot commented Jun 3, 2026

Approvability

Verdict: Needs human review

This virtualization optimization has an unresolved review comment identifying a scroll position bug where the highlighted item may be off-screen after filtering. This functional issue should be addressed before merging.

You can customize Macroscope's approvability policy. Learn more.

@chanyeinthaw chanyeinthaw changed the title Virtualize model picker fix(web): Virtualize model picker Jun 3, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:L 100-499 changed lines (additions + deletions). vouch:unvouched PR author is not yet trusted in the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant