-
-
Notifications
You must be signed in to change notification settings - Fork 155
Description
Describe the bug
When using Bits UI Combobox/Select components with virtual scrolling libraries (like virtua
), keyboard navigation breaks because the focus automatically resets to the first item whenever new virtual list items are mounted to the DOM.
Expected Behavior
Arrow key navigation should maintain the current highlighted position when scrolling through a virtual list, allowing users to navigate through large datasets smoothly.
Actual Behavior
When navigating with arrow keys in a virtual list:
- User navigates to the last visible item (ie. 6) using arrow keys
- Virtual list adds new DOM nodes for items 7-10
- Focus automatically jumps back to item 0/1 (first item)
- User loses their navigation position
Root Cause
The issue occurs in SelectItemState
constructor where onMountEffect
and onDestroyEffect
both call setHighlightedToFirstCandidate({ debounced: true })
whenever any item mounts or unmounts. In virtual lists, items are constantly mounting/unmounting as the user scrolls, causing unwanted focus resets.
Problematic code:
onMountEffect(() => {
this.root.setHighlightedToFirstCandidate({ debounced: true });
});
onDestroyEffect(() => {
this.root.setHighlightedToFirstCandidate({ debounced: true });
`});
Proposed Solution
I was able to fix the problem by adding a 'vList' property on the content element and checking for this before calling first candidate function.
Add conditional logic to detect virtual list contexts and skip the focus reset:
onMountEffect(() => {
// Skip highlight reset for virtual lists
if (this.root.contentNode?.hasAttribute('vList')) return;
this.root.setHighlightedToFirstCandidate({ debounced: true });
});
onDestroyEffect(() => {
// Skip highlight reset for virtual lists
if (this.root.contentNode?.hasAttribute('vList')) return;
this.root.setHighlightedToFirstCandidate({ debounced: true });
});
Reproduction
https://stackblitz.com/edit/github-zt1racgs?file=src%2Froutes%2F%2Bpage.svelte
Logs
System Info
System:
OS: macOS 15.0.1
CPU: (12) arm64 Apple M2 Max
Memory: 88.30 MB / 32.00 GB
Shell: 5.9 - /bin/zsh
Binaries:
Node: 24.4.1 - ~/.nvm/versions/node/v24.4.1/bin/node
npm: 11.4.2 - ~/.nvm/versions/node/v24.4.1/bin/npm
pnpm: 8.12.1 - ~/Library/pnpm/pnpm
Browsers:
Brave Browser: 138.1.80.122
Chrome: 138.0.7204.184
Safari: 18.0.1
npmPackages:
@sveltejs/kit: ^2.12.0 => 2.26.0
bits-ui: ^2.8.0 => 2.8.11
svelte: ^5.20.2 => 5.36.16
Severity
annoyance