ITADN

Combobox: oninput calls setHighlightedToFirstCandidate before DOM updates with filtered items

#1996Closedfranzwarning 创建于 2026-03-26
awaiting submitter
F
franzwarningcommented
## Description When using the Combobox with custom filtering (rendering a filtered subset of items via `{#each filteredItems}`), typing in the input does not highlight the first candidate item. This means pressing Enter doesn't select anything. ## Root Cause In `SelectInputState.oninput` ([select.svelte.js](https://github.com/huntabyte/bits-ui/blob/main/packages/bits-ui/src/lib/bits/select/select.svelte.ts)), `setHighlightedToFirstCandidate()` is called synchronously: ```js oninput(e) { this.root.opts.inputValue.current = e.currentTarget.value; this.root.setHighlightedToFirstCandidate(); // runs before DOM updates } ``` At this point, Svelte hasn't re-rendered the filtered items yet, so `getCandidateNodes()` queries stale DOM nodes. The highlighted node ends up being `null`. ## Expected Fix Wrap the call with `afterTick()`, which is already used elsewhere in the same file (e.g., `setInitialHighlightedNode` on open): ```js oninput(e) { this.root.opts.inputValue.current = e.currentTarget.value; afterTick(() => { this.root.setHighlightedToFirstCandidate(); }); } ``` ## Reproduction 1. Create a Combobox with custom filtering per the docs example: ```svelte <script lang="ts"> import { Combobox } from "bits-ui"; const items = [ { value: "apple", label: "Apple" }, { value: "banana", label: "Banana" }, { value: "cherry", label: "Cherry" }, ]; let searchValue = $state(""); const filteredItems = $derived( searchValue === "" ? items : items.filter((item) => item.label.toLowerCase().includes(searchValue.toLowerCase()) ) ); </script> <Combobox.Root type="single" onOpenChangeComplete={(o) => { if (!o) searchValue = ""; }}> <Combobox.Input oninput={(e) => (searchValue = e.currentTarget.value)} placeholder="Search..." /> <Combobox.Portal> <Combobox.Content> <Combobox.Viewport> {#each filteredItems as item (item.value)} <Combobox.Item value={item.value} label={item.label}> {item.label} </Combobox.Item> {/each} </Combobox.Viewport> </Combobox.Content> </Combobox.Portal> </Combobox.Root> ``` 2. Type "ch" — only "Cherry" appears 3. No item is highlighted (no `data-highlighted` attribute) 4. Pressing Enter does nothing ## Environment - bits-ui: ^2.x (latest) - Svelte 5
关闭于 2026-04-11 2 条评论