fix(ui): keep command picker highlight in sync

This commit is contained in:
Shantur Rathore
2026-02-07 22:38:17 +00:00
parent 4097637169
commit 6b81d0d703

View File

@@ -103,6 +103,7 @@ const UnifiedPicker: Component<UnifiedPickerProps> = (props) => {
let scrollContainerRef: HTMLDivElement | undefined let scrollContainerRef: HTMLDivElement | undefined
let lastWorkspaceId: string | null = null let lastWorkspaceId: string | null = null
let lastQuery = "" let lastQuery = ""
let lastCommandQuery = ""
let inflightWorkspaceId: string | null = null let inflightWorkspaceId: string | null = null
let inflightSnapshotPromise: Promise<FileItem[]> | null = null let inflightSnapshotPromise: Promise<FileItem[]> | null = null
let activeRequestId = 0 let activeRequestId = 0
@@ -243,6 +244,7 @@ const UnifiedPicker: Component<UnifiedPickerProps> = (props) => {
setLoadingState("idle") setLoadingState("idle")
lastWorkspaceId = null lastWorkspaceId = null
lastQuery = "" lastQuery = ""
lastCommandQuery = ""
activeRequestId = 0 activeRequestId = 0
} }
@@ -273,8 +275,6 @@ const UnifiedPicker: Component<UnifiedPickerProps> = (props) => {
} }
}) })
createEffect(() => { createEffect(() => {
if (!props.open) return if (!props.open) return
if (mode() !== "mention") return if (mode() !== "mention") return
@@ -303,6 +303,37 @@ const UnifiedPicker: Component<UnifiedPickerProps> = (props) => {
}) })
}) })
createEffect(() => {
if (!props.open) return
if (mode() !== "command") return
const query = props.searchQuery
const count = filteredCommands().length
if (query !== lastCommandQuery) {
lastCommandQuery = query
setSelectedIndex(0)
resetScrollPosition()
return
}
if (count <= 0) {
if (selectedIndex() !== 0) {
setSelectedIndex(0)
}
return
}
const current = selectedIndex()
if (current < 0) {
setSelectedIndex(0)
return
}
if (current >= count) {
setSelectedIndex(count - 1)
}
})
const allItems = (): PickerItem[] => { const allItems = (): PickerItem[] => {
const items: PickerItem[] = [] const items: PickerItem[] = []
if (mode() === "command") { if (mode() === "command") {
@@ -335,20 +366,24 @@ const UnifiedPicker: Component<UnifiedPickerProps> = (props) => {
if (e.key === "ArrowDown") { if (e.key === "ArrowDown") {
e.preventDefault() e.preventDefault()
e.stopPropagation()
setSelectedIndex((prev) => Math.min(prev + 1, items.length - 1)) setSelectedIndex((prev) => Math.min(prev + 1, items.length - 1))
scrollToSelected() scrollToSelected()
} else if (e.key === "ArrowUp") { } else if (e.key === "ArrowUp") {
e.preventDefault() e.preventDefault()
e.stopPropagation()
setSelectedIndex((prev) => Math.max(prev - 1, 0)) setSelectedIndex((prev) => Math.max(prev - 1, 0))
scrollToSelected() scrollToSelected()
} else if (e.key === "Enter" || e.key === "Tab") { } else if (e.key === "Enter" || e.key === "Tab") {
e.preventDefault() e.preventDefault()
e.stopPropagation()
const selected = items[selectedIndex()] const selected = items[selectedIndex()]
if (selected) { if (selected) {
handleSelect(selected) handleSelect(selected)
} }
} else if (e.key === "Escape") { } else if (e.key === "Escape") {
e.preventDefault() e.preventDefault()
e.stopPropagation()
props.onClose() props.onClose()
} }
} }
@@ -402,12 +437,12 @@ const UnifiedPicker: Component<UnifiedPickerProps> = (props) => {
<Show when={mode() === "command" && commandCount() > 0}> <Show when={mode() === "command" && commandCount() > 0}>
<div class="dropdown-section-header">{t("unifiedPicker.sections.commands")}</div> <div class="dropdown-section-header">{t("unifiedPicker.sections.commands")}</div>
<For each={filteredCommands()}> <For each={filteredCommands()}>
{(command) => { {(command, index) => {
const itemIndex = allItems().findIndex((item) => item.type === "command" && item.command.name === command.name) const isSelected = () => index() === selectedIndex()
return ( return (
<div <div
class={`dropdown-item ${itemIndex === selectedIndex() ? "dropdown-item-highlight" : ""}`} class={`dropdown-item ${isSelected() ? "dropdown-item-highlight" : ""}`}
data-picker-selected={itemIndex === selectedIndex()} data-picker-selected={isSelected()}
onClick={() => handleSelect({ type: "command", command })} onClick={() => handleSelect({ type: "command", command })}
> >
<div class="flex items-start gap-2"> <div class="flex items-start gap-2">