@@ -44,6 +44,8 @@ export const ModeSelector = ({
4444 const [ open , setOpen ] = React . useState ( false )
4545 const [ searchValue , setSearchValue ] = React . useState ( "" )
4646 const searchInputRef = React . useRef < HTMLInputElement > ( null )
47+ const selectedItemRef = React . useRef < HTMLDivElement > ( null )
48+ const scrollContainerRef = React . useRef < HTMLDivElement > ( null )
4749 const portalContainer = useRooPortal ( "roo-portal" )
4850 const { hasOpenedModeSelector, setHasOpenedModeSelector } = useExtensionState ( )
4951 const { t } = useAppTranslation ( )
@@ -149,10 +151,37 @@ export const ModeSelector = ({
149151 [ trackModeSelectorOpened ] ,
150152 )
151153
152- // Auto-focus search input when popover opens.
154+ // Auto-focus search input and scroll to selected item when popover opens.
153155 React . useEffect ( ( ) => {
154- if ( open && searchInputRef . current ) {
155- searchInputRef . current . focus ( )
156+ if ( open ) {
157+ // Focus search input
158+ if ( searchInputRef . current ) {
159+ searchInputRef . current . focus ( )
160+ }
161+
162+ requestAnimationFrame ( ( ) => {
163+ if ( selectedItemRef . current && scrollContainerRef . current ) {
164+ const container = scrollContainerRef . current
165+ const item = selectedItemRef . current
166+
167+ // Calculate positions
168+ const containerHeight = container . clientHeight
169+ const itemTop = item . offsetTop
170+ const itemHeight = item . offsetHeight
171+
172+ // Center the item in the container
173+ const scrollPosition = itemTop - containerHeight / 2 + itemHeight / 2
174+
175+ // Ensure we don't scroll past boundaries
176+ const maxScroll = container . scrollHeight - containerHeight
177+ const finalScrollPosition = Math . min ( Math . max ( 0 , scrollPosition ) , maxScroll )
178+
179+ container . scrollTo ( {
180+ top : finalScrollPosition ,
181+ behavior : "instant" ,
182+ } )
183+ }
184+ } )
156185 }
157186 } , [ open ] )
158187
@@ -223,36 +252,40 @@ export const ModeSelector = ({
223252 ) }
224253
225254 { /* Mode List */ }
226- < div className = "max-h-[300px] overflow-y-auto" >
255+ < div ref = { scrollContainerRef } className = "max-h-[300px] overflow-y-auto" >
227256 { filteredModes . length === 0 && searchValue ? (
228257 < div className = "py-2 px-3 text-sm text-vscode-foreground/70" >
229258 { t ( "chat:modeSelector.noResults" ) }
230259 </ div >
231260 ) : (
232261 < div className = "py-1" >
233- { filteredModes . map ( ( mode ) => (
234- < div
235- key = { mode . slug }
236- onClick = { ( ) => handleSelect ( mode . slug ) }
237- className = { cn (
238- "px-3 py-1.5 text-sm cursor-pointer flex items-center" ,
239- "hover:bg-vscode-list-hoverBackground" ,
240- mode . slug === value
241- ? "bg-vscode-list-activeSelectionBackground text-vscode-list-activeSelectionForeground"
242- : "" ,
243- ) }
244- data-testid = "mode-selector-item" >
245- < div className = "flex-1 min-w-0" >
246- < div className = "font-bold truncate" > { mode . name } </ div >
247- { mode . description && (
248- < div className = "text-xs text-vscode-descriptionForeground truncate" >
249- { mode . description }
250- </ div >
262+ { filteredModes . map ( ( mode ) => {
263+ const isSelected = mode . slug === value
264+ return (
265+ < div
266+ key = { mode . slug }
267+ ref = { isSelected ? selectedItemRef : null }
268+ onClick = { ( ) => handleSelect ( mode . slug ) }
269+ className = { cn (
270+ "px-3 py-1.5 text-sm cursor-pointer flex items-center" ,
271+ "hover:bg-vscode-list-hoverBackground" ,
272+ isSelected
273+ ? "bg-vscode-list-activeSelectionBackground text-vscode-list-activeSelectionForeground"
274+ : "" ,
251275 ) }
276+ data-testid = "mode-selector-item" >
277+ < div className = "flex-1 min-w-0" >
278+ < div className = "font-bold truncate" > { mode . name } </ div >
279+ { mode . description && (
280+ < div className = "text-xs text-vscode-descriptionForeground truncate" >
281+ { mode . description }
282+ </ div >
283+ ) }
284+ </ div >
285+ { isSelected && < Check className = "ml-auto size-4 p-0.5" /> }
252286 </ div >
253- { mode . slug === value && < Check className = "ml-auto size-4 p-0.5" /> }
254- </ div >
255- ) ) }
287+ )
288+ } ) }
256289 </ div >
257290 ) }
258291 </ div >
0 commit comments