Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Conversation

@simeonlee
Copy link
Member

@simeonlee simeonlee commented Jan 22, 2026

Summary

  • Adds @tanstack/react-virtual for efficient rendering of large lists (100+ items)
  • Implements virtualizeThreshold prop (default: 100) for both Combobox and ButtonSelect
  • Adds custom keyboard navigation for virtualized mode (Arrow keys, Home/End, PageUp/PageDown)
  • Creates shared VirtualizedCommandItems component used by both components
  • Adds comprehensive Storybook stories for testing virtualization edge cases

Test plan

  • Verify virtualization kicks in at 100+ items in Storybook (UI/Combobox and UI/ButtonSelect)
  • Test keyboard navigation in virtualized mode (arrow keys, Home/End, PageUp/PageDown)
  • Verify filtering works correctly with virtualization
  • Test creation mode with virtualization enabled
  • Confirm no visual differences between virtualized and non-virtualized rendering

Note

Introduces efficient list virtualization for large dropdowns and aligned Storybook coverage.

  • Adds @tanstack/react-virtual and new shared VirtualizedCommandItems to render cmdk lists efficiently
  • Extends Combobox and ButtonSelect with virtualizeThreshold (default: 100), toggling between virtualized and non-virtualized rendering
  • Implements virtualized-mode keyboard navigation (Arrow keys, Home/End, PageUp/PageDown, Enter/Escape) with highlighted index management and auto-scroll
  • Refactors ComboboxMenuItems to support virtualization and explicit item highlighting
  • Adds comprehensive Storybook stories (virtualized, forced/disabled, stress tests, filtering, creation, keyboard nav)
  • Updates ui/package.json and lockfile to include @tanstack/react-virtual

Written by Cursor Bugbot for commit be29ca5. This will update automatically on new commits. Configure here.

@simeonlee simeonlee self-assigned this Jan 22, 2026
Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: be29ca5ffe

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

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".

Comment on lines +191 to +195
if (e.key === "Enter") {
e.preventDefault();
const item = filteredItems[highlightedIndex];
if (item) {
handleSelectItem(item.value, false);

Choose a reason for hiding this comment

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

P2 Badge Handle create option on Enter in virtualized combobox

In virtualized mode, Enter always selects filteredItems[highlightedIndex], but the create option is rendered separately and never included in the highlighted index. This means when allowCreation is true and the search text doesn’t match an existing item (showCreateOption), pressing Enter won’t create the new item (it will no-op on an empty list or select the first existing item), which is a regression from the non-virtualized cmdk behavior where the create item is keyboard-selectable.

Useful? React with 👍 / 👎.

Comment on lines +195 to +199
if (e.key === "Enter") {
e.preventDefault();
const item = filteredItems[highlightedIndex];
if (item) {
handleSelectItem(item, false);

Choose a reason for hiding this comment

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

P2 Badge Handle create option on Enter in virtualized button select

The virtualized key handler always uses filteredItems[highlightedIndex] on Enter and never considers the create option that appears when creatable is true and the search text is new. As a result, keyboard creation is broken in virtualized mode (Enter does nothing when the filtered list is empty or selects the first existing item instead of creating), which differs from the non-virtualized cmdk behavior.

Useful? React with 👍 / 👎.

Copy link

@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 2 potential issues.

Bugbot Autofix is OFF. To automatically fix reported issues with Cloud Agents, enable Autofix in the Cursor dashboard.

handleSelectItem(item.value, false);
}
return;
}
Copy link

Choose a reason for hiding this comment

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

Create option unreachable via keyboard in virtualized mode

Medium Severity

The virtualized keyboard Enter handler only accesses filteredItems[highlightedIndex] and always passes isNew: false to handleSelectItem. The "create new" option is rendered separately in ComboboxMenuItems (via its own CommandItem with onSelect={() => onSelectItem(searchValue.trim(), true)}), but highlightedIndex only tracks position within filteredItems. This makes the create option completely unreachable via keyboard navigation when virtualization is active, breaking the VirtualizedWithCreation use case in both components.

Additional Locations (1)

Fix in Cursor Fix in Web

setHighlightedIndex((prev) =>
Math.min(prev + 8, filteredItems.length - 1),
);
return;
Copy link

Choose a reason for hiding this comment

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

PageDown sets invalid negative index when list empty

Low Severity

The PageDown handler uses Math.min(prev + 8, filteredItems.length - 1) which returns -1 when filteredItems is empty (since Math.min(8, -1) equals -1). Unlike the End key handler which uses Math.max(0, ...) for protection, and the useEffect which has an explicit if (filteredItems.length === 0) return 0 guard, PageDown lacks empty list handling. This causes highlightedIndex to become -1, resulting in no visual highlighting and Enter doing nothing until the user presses ArrowDown to recover.

Additional Locations (1)

Fix in Cursor Fix in Web

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants