diff --git a/webview-ui/src/components/chat/ModeSelector.tsx b/webview-ui/src/components/chat/ModeSelector.tsx index 2ae9279fa8e..331660143b7 100644 --- a/webview-ui/src/components/chat/ModeSelector.tsx +++ b/webview-ui/src/components/chat/ModeSelector.tsx @@ -44,6 +44,8 @@ export const ModeSelector = ({ const [open, setOpen] = React.useState(false) const [searchValue, setSearchValue] = React.useState("") const searchInputRef = React.useRef(null) + const selectedItemRef = React.useRef(null) + const scrollContainerRef = React.useRef(null) const portalContainer = useRooPortal("roo-portal") const { hasOpenedModeSelector, setHasOpenedModeSelector } = useExtensionState() const { t } = useAppTranslation() @@ -149,10 +151,37 @@ export const ModeSelector = ({ [trackModeSelectorOpened], ) - // Auto-focus search input when popover opens. + // Auto-focus search input and scroll to selected item when popover opens. React.useEffect(() => { - if (open && searchInputRef.current) { - searchInputRef.current.focus() + if (open) { + // Focus search input + if (searchInputRef.current) { + searchInputRef.current.focus() + } + + requestAnimationFrame(() => { + if (selectedItemRef.current && scrollContainerRef.current) { + const container = scrollContainerRef.current + const item = selectedItemRef.current + + // Calculate positions + const containerHeight = container.clientHeight + const itemTop = item.offsetTop + const itemHeight = item.offsetHeight + + // Center the item in the container + const scrollPosition = itemTop - containerHeight / 2 + itemHeight / 2 + + // Ensure we don't scroll past boundaries + const maxScroll = container.scrollHeight - containerHeight + const finalScrollPosition = Math.min(Math.max(0, scrollPosition), maxScroll) + + container.scrollTo({ + top: finalScrollPosition, + behavior: "instant", + }) + } + }) } }, [open]) @@ -223,36 +252,40 @@ export const ModeSelector = ({ )} {/* Mode List */} -
+
{filteredModes.length === 0 && searchValue ? (
{t("chat:modeSelector.noResults")}
) : (
- {filteredModes.map((mode) => ( -
handleSelect(mode.slug)} - className={cn( - "px-3 py-1.5 text-sm cursor-pointer flex items-center", - "hover:bg-vscode-list-hoverBackground", - mode.slug === value - ? "bg-vscode-list-activeSelectionBackground text-vscode-list-activeSelectionForeground" - : "", - )} - data-testid="mode-selector-item"> -
-
{mode.name}
- {mode.description && ( -
- {mode.description} -
+ {filteredModes.map((mode) => { + const isSelected = mode.slug === value + return ( +
handleSelect(mode.slug)} + className={cn( + "px-3 py-1.5 text-sm cursor-pointer flex items-center", + "hover:bg-vscode-list-hoverBackground", + isSelected + ? "bg-vscode-list-activeSelectionBackground text-vscode-list-activeSelectionForeground" + : "", )} + data-testid="mode-selector-item"> +
+
{mode.name}
+ {mode.description && ( +
+ {mode.description} +
+ )} +
+ {isSelected && }
- {mode.slug === value && } -
- ))} + ) + })}
)}