refactor: commandline#46
Conversation
Greptile SummaryThis PR refactors the commandline feature by extracting all stateful logic into a
Confidence Score: 3/5Not safe to merge as-is: clicking a command palette item can silently execute the wrong command when the cursor hasn't moved since the palette opened. The click-selection path now ignores the specific item passed by the list and relies entirely on selectedIndex, which is only updated via pointer-move events. A user who opens the palette and immediately clicks an item (cursor stationary) will trigger whatever command is at selectedIndex (defaulting to 0), not the one they clicked. Combined with other regressions carried over from previous review rounds, the commandline's core interaction loop is unreliable. apps/frontend/src/features/commandline/components/commandline.tsx — the onSelectItem wiring and the inlined CommandlineInput styling both need attention.
|
| Filename | Overview |
|---|---|
| apps/frontend/src/features/commandline/components/commandline.tsx | Major refactor extracts logic into createCommandlineController; introduces a click-selection bug where selectCurrent ignores the item passed by CommandlineList and uses selectedIndex instead, running the wrong command when the pointer hasn't hovered an item since the palette opened. |
| apps/frontend/src/features/commandline/components/commandline-input.tsx | File deleted; its contents were inlined into commandline.tsx with minor styling differences (bg-transparent and text-(--text) removed from the input class). |
| apps/frontend/src/app/layout.tsx | Import updated from default to named export — trivial, safe change. |
Reviews (2): Last reviewed commit: "mobile" | Re-trigger Greptile
| createEffect(() => { | ||
| if (cmd.scope() === "themes" && cmd.isOpen()) { | ||
| const item = cmd.visibleItems()[cmd.selectedIndex()]; | ||
|
|
||
| if (item && item.id.startsWith("theme-")) { | ||
| themeManager.preview(item.id.replace("theme-", "") as any); | ||
| } | ||
|
|
||
| return; | ||
| } | ||
|
|
||
| if (cmd.isOpen()) { | ||
| themeManager.reset(); | ||
| } | ||
| }); |
There was a problem hiding this comment.
themeManager.reset() not called when closing from the themes scope
The close() action calls setScope("root") and setIsOpen(false) synchronously in the same call frame. SolidJS defers createEffect callbacks until after all synchronous signal writes complete, so by the time the theme effect runs, both scope() = "root" and isOpen() = false. Neither branch of the effect fires (isOpen() is falsy), so themeManager.reset() is skipped. If a user previews a theme and then clicks the backdrop to close the palette, the previewed theme is never reverted.
| <CommandlineList | ||
| items={cmd.visibleItems()} | ||
| selectedIndex={cmd.selectedIndex()} | ||
| scope={cmd.scope()} | ||
| interactionType={cmd.interactionType()} | ||
| onHoverItem={cmd.hoverItem} | ||
| onSelectItem={cmd.selectCurrent} | ||
| /> |
There was a problem hiding this comment.
Wrong item executed on click when pointer hasn't moved
CommandlineList calls props.onSelectItem(item) passing the specific clicked item (line 75 of commandline-list.tsx), but cmd.selectCurrent ignores its argument and instead fetches visibleItems()[selectedIndex()]. If the user opens the palette and clicks an item without having moved the pointer after opening (so onPointerMove never ran to update selectedIndex), selectCurrent will execute the command at the default selectedIndex (typically 0) instead of the clicked one. TypeScript silently accepts a () => void where (item: CommandlineItemType) => void is expected, so there is no compile-time warning.
No description provided.