fix: distinguish hover and selection states in

context menu

Improve the context menu UX by separating
hover and selection visual states. Previously,
hovering would immediately change the
selected index, making it difficult to
distinguish between the actively selected item
and the item being hovered over.

Changes:
- Add separate hoveredIndex state to track
mouse hover independently from selection
- Apply different background colors for hover
vs selection states
- Update mouse event handlers to properly
manage hover state
- Reset hover state when search query changes
This commit is contained in:
heyseth 2025-11-06 16:08:32 -08:00
parent 49e57ed0fa
commit eac11c12e0

View file

@ -46,6 +46,7 @@ const ContextMenu: React.FC<ContextMenuProps> = ({
}) => {
const [materialIconsBaseUri, setMaterialIconsBaseUri] = useState("")
const menuRef = useRef<HTMLDivElement>(null)
const [hoveredIndex, setHoveredIndex] = useState<number | null>(null)
const filteredOptions = useMemo(() => {
return getContextMenuOptions(searchQuery, selectedType, queryItems, dynamicSearchResults, modes, commands)
@ -73,6 +74,11 @@ const ContextMenu: React.FC<ContextMenuProps> = ({
setMaterialIconsBaseUri(w.MATERIAL_ICONS_BASE_URI)
}, [])
// Reset hover state when menu opens/closes
useEffect(() => {
setHoveredIndex(null)
}, [searchQuery])
const renderOptionContent = (option: ContextMenuQueryItem) => {
switch (option.type) {
case ContextMenuOptionType.SectionHeader:
@ -340,14 +346,18 @@ const ContextMenu: React.FC<ContextMenuProps> = ({
filteredOptions.map((option, index) => (
<div
key={`${option.type}-${option.value || index}`}
onClick={() => isOptionSelectable(option) && onSelect(option.type, option.value)}
onClick={() => {
if (isOptionSelectable(option)) {
setSelectedIndex(index)
onSelect(option.type, option.value)
}
}}
style={{
padding:
option.type === ContextMenuOptionType.SectionHeader
? "16px 8px 4px 8px"
: "4px 8px",
cursor: isOptionSelectable(option) ? "pointer" : "default",
color: "var(--vscode-dropdown-foreground)",
display: "flex",
alignItems: "center",
justifyContent: "space-between",
@ -358,14 +368,31 @@ const ContextMenu: React.FC<ContextMenuProps> = ({
marginBottom: "2px",
}
: {}),
// Show different styles for selection vs hover
...(index === selectedIndex && isOptionSelectable(option)
? {
backgroundColor: "var(--vscode-list-activeSelectionBackground)",
color: "var(--vscode-list-activeSelectionForeground)",
}
: {}),
: index === hoveredIndex && isOptionSelectable(option)
? {
backgroundColor: "var(--vscode-list-hoverBackground)",
color: "var(--vscode-dropdown-foreground)",
}
: {
color: "var(--vscode-dropdown-foreground)",
}),
}}
onMouseEnter={() => isOptionSelectable(option) && setSelectedIndex(index)}>
onMouseEnter={() => {
if (isOptionSelectable(option)) {
setHoveredIndex(index)
}
}}
onMouseLeave={() => {
if (index === hoveredIndex) {
setHoveredIndex(null)
}
}}>
<div
style={{
display: "flex",