mirror of
https://github.com/RooVetGit/Roo-Code.git
synced 2026-09-07 08:26:51 +00:00
fix: center active mode in selector dropdown on open (#7883)
Co-authored-by: Roo Code <roomote@roocode.com> Co-authored-by: daniel-lxs <ricciodaniel98@gmail.com>
This commit is contained in:
parent
ad8551868e
commit
a9e22f0df0
1 changed files with 58 additions and 25 deletions
|
|
@ -44,6 +44,8 @@ export const ModeSelector = ({
|
|||
const [open, setOpen] = React.useState(false)
|
||||
const [searchValue, setSearchValue] = React.useState("")
|
||||
const searchInputRef = React.useRef<HTMLInputElement>(null)
|
||||
const selectedItemRef = React.useRef<HTMLDivElement>(null)
|
||||
const scrollContainerRef = React.useRef<HTMLDivElement>(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 */}
|
||||
<div className="max-h-[300px] overflow-y-auto">
|
||||
<div ref={scrollContainerRef} className="max-h-[300px] overflow-y-auto">
|
||||
{filteredModes.length === 0 && searchValue ? (
|
||||
<div className="py-2 px-3 text-sm text-vscode-foreground/70">
|
||||
{t("chat:modeSelector.noResults")}
|
||||
</div>
|
||||
) : (
|
||||
<div className="py-1">
|
||||
{filteredModes.map((mode) => (
|
||||
<div
|
||||
key={mode.slug}
|
||||
onClick={() => 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">
|
||||
<div className="flex-1 min-w-0">
|
||||
<div className="font-bold truncate">{mode.name}</div>
|
||||
{mode.description && (
|
||||
<div className="text-xs text-vscode-descriptionForeground truncate">
|
||||
{mode.description}
|
||||
</div>
|
||||
{filteredModes.map((mode) => {
|
||||
const isSelected = mode.slug === value
|
||||
return (
|
||||
<div
|
||||
key={mode.slug}
|
||||
ref={isSelected ? selectedItemRef : null}
|
||||
onClick={() => 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">
|
||||
<div className="flex-1 min-w-0">
|
||||
<div className="font-bold truncate">{mode.name}</div>
|
||||
{mode.description && (
|
||||
<div className="text-xs text-vscode-descriptionForeground truncate">
|
||||
{mode.description}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
{isSelected && <Check className="ml-auto size-4 p-0.5" />}
|
||||
</div>
|
||||
{mode.slug === value && <Check className="ml-auto size-4 p-0.5" />}
|
||||
</div>
|
||||
))}
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue