From dcf8ba67b457ffe4a278efd28956a46f2186fb7e Mon Sep 17 00:00:00 2001 From: ethan Date: Tue, 9 Dec 2025 18:32:50 +1100 Subject: [PATCH] =?UTF-8?q?=F0=9F=A4=96=20fix:=20scroll=20slash=20command?= =?UTF-8?q?=20suggestions=20to=20follow=20keyboard=20selection?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When navigating slash commands with arrow keys, the dropdown now scrolls to keep the selected item visible. Previously, the selection would move outside the visible area without the view following. _Generated with mux_ --- src/browser/components/CommandSuggestions.tsx | 7 +++++++ src/browser/stories/App.chat.stories.tsx | 9 ++++++--- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/src/browser/components/CommandSuggestions.tsx b/src/browser/components/CommandSuggestions.tsx index 7aa47b66fc..7373142a68 100644 --- a/src/browser/components/CommandSuggestions.tsx +++ b/src/browser/components/CommandSuggestions.tsx @@ -33,12 +33,18 @@ export const CommandSuggestions: React.FC = ({ null ); const menuRef = useRef(null); + const selectedRef = useRef(null); // Reset selection whenever suggestions change useEffect(() => { setSelectedIndex(0); }, [suggestions]); + // Scroll selected item into view + useEffect(() => { + selectedRef.current?.scrollIntoView({ block: "nearest" }); + }, [selectedIndex]); + // Calculate position when using portal mode useLayoutEffect(() => { if (!anchorRef?.current || !isVisible) { @@ -153,6 +159,7 @@ export const CommandSuggestions: React.FC = ({ {suggestions.map((suggestion, index) => (
setSelectedIndex(index)} onClick={() => onSelectSuggestion(suggestion)} id={`${resolvedListId}-option-${suggestion.id}`} diff --git a/src/browser/stories/App.chat.stories.tsx b/src/browser/stories/App.chat.stories.tsx index 59cd662a26..c17c056f4a 100644 --- a/src/browser/stories/App.chat.stories.tsx +++ b/src/browser/stories/App.chat.stories.tsx @@ -249,7 +249,8 @@ npm test 2>&1 | head -20`, const toolHeader = canvas.getByText(/set -e/); await userEvent.click(toolHeader); }); - // Remove unintended focus state for deterministic visual snapshot + // Wait for any auto-focus timers (ChatInput has 100ms delay), then blur + await new Promise((resolve) => setTimeout(resolve, 150)); (document.activeElement as HTMLElement)?.blur(); }, }; @@ -299,7 +300,8 @@ export const WithBashToolWaiting: AppStory = { const toolHeader = canvas.getByText(/npm test/); await userEvent.click(toolHeader); }); - // Remove unintended focus state for deterministic visual snapshot + // Wait for any auto-focus timers (ChatInput has 100ms delay), then blur + await new Promise((resolve) => setTimeout(resolve, 150)); (document.activeElement as HTMLElement)?.blur(); }, }; @@ -448,7 +450,8 @@ export const GenericTool: AppStory = { const toolHeader = canvas.getByText("fetch_data"); await userEvent.click(toolHeader); }); - // Remove unintended focus state for deterministic visual snapshot + // Wait for any auto-focus timers (ChatInput has 100ms delay), then blur + await new Promise((resolve) => setTimeout(resolve, 150)); (document.activeElement as HTMLElement)?.blur(); }, };