Skip to content

Commit e91ee5e

Browse files
🤖 fix: scroll slash command suggestions to follow keyboard selection (#1014)
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`_
1 parent 88b6321 commit e91ee5e

File tree

2 files changed

+13
-3
lines changed

2 files changed

+13
-3
lines changed

‎src/browser/components/CommandSuggestions.tsx‎

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,12 +33,18 @@ export const CommandSuggestions: React.FC<CommandSuggestionsProps> = ({
3333
null
3434
);
3535
const menuRef = useRef<HTMLDivElement>(null);
36+
const selectedRef = useRef<HTMLDivElement>(null);
3637

3738
// Reset selection whenever suggestions change
3839
useEffect(() => {
3940
setSelectedIndex(0);
4041
}, [suggestions]);
4142

43+
// Scroll selected item into view
44+
useEffect(() => {
45+
selectedRef.current?.scrollIntoView({ block: "nearest" });
46+
}, [selectedIndex]);
47+
4248
// Calculate position when using portal mode
4349
useLayoutEffect(() => {
4450
if (!anchorRef?.current || !isVisible) {
@@ -153,6 +159,7 @@ export const CommandSuggestions: React.FC<CommandSuggestionsProps> = ({
153159
{suggestions.map((suggestion, index) => (
154160
<div
155161
key={suggestion.id}
162+
ref={index === selectedIndex ? selectedRef : undefined}
156163
onMouseEnter={() => setSelectedIndex(index)}
157164
onClick={() => onSelectSuggestion(suggestion)}
158165
id={`${resolvedListId}-option-${suggestion.id}`}

‎src/browser/stories/App.chat.stories.tsx‎

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -249,7 +249,8 @@ npm test 2>&1 | head -20`,
249249
const toolHeader = canvas.getByText(/set -e/);
250250
await userEvent.click(toolHeader);
251251
});
252-
// Remove unintended focus state for deterministic visual snapshot
252+
// Wait for any auto-focus timers (ChatInput has 100ms delay), then blur
253+
await new Promise((resolve) => setTimeout(resolve, 150));
253254
(document.activeElement as HTMLElement)?.blur();
254255
},
255256
};
@@ -299,7 +300,8 @@ export const WithBashToolWaiting: AppStory = {
299300
const toolHeader = canvas.getByText(/npm test/);
300301
await userEvent.click(toolHeader);
301302
});
302-
// Remove unintended focus state for deterministic visual snapshot
303+
// Wait for any auto-focus timers (ChatInput has 100ms delay), then blur
304+
await new Promise((resolve) => setTimeout(resolve, 150));
303305
(document.activeElement as HTMLElement)?.blur();
304306
},
305307
};
@@ -448,7 +450,8 @@ export const GenericTool: AppStory = {
448450
const toolHeader = canvas.getByText("fetch_data");
449451
await userEvent.click(toolHeader);
450452
});
451-
// Remove unintended focus state for deterministic visual snapshot
453+
// Wait for any auto-focus timers (ChatInput has 100ms delay), then blur
454+
await new Promise((resolve) => setTimeout(resolve, 150));
452455
(document.activeElement as HTMLElement)?.blur();
453456
},
454457
};

0 commit comments

Comments
 (0)