MCPcopy Index your code
hub / github.com/CodebuffAI/codebuff / SuggestionMenu

Function SuggestionMenu

cli/src/components/suggestion-menu.tsx:24–207  ·  view source on GitHub ↗
({
  items,
  selectedIndex,
  maxVisible,
  prefix = '/',
  onItemClick,
}: SuggestionMenuProps)

Source from the content-addressed store, hash-verified

22}
23
24export const SuggestionMenu = ({
25 items,
26 selectedIndex,
27 maxVisible,
28 prefix = '/',
29 onItemClick,
30}: SuggestionMenuProps) => {
31 const theme = useTheme()
32 const { terminalWidth } = useTerminalDimensions()
33 const screenPadding = 4
34 const menuWidth = Math.max(10, terminalWidth - screenPadding * 2)
35
36 // Hover state: only highlight on hover after user has moved mouse
37 const [hoveredIndex, setHoveredIndex] = useState<number | null>(null)
38 const [hasHoveredSinceOpen, setHasHoveredSinceOpen] = useState(false)
39
40 // Reset hover state when items change (new menu session)
41 useEffect(() => {
42 setHasHoveredSinceOpen(false)
43 setHoveredIndex(null)
44 }, [items])
45
46 if (items.length === 0) {
47 return null
48 }
49
50 const effectivePrefix = prefix ?? ''
51
52 const clampedSelected = Math.min(
53 Math.max(selectedIndex, 0),
54 Math.max(items.length - 1, 0),
55 )
56 const visibleCount = Math.min(Math.max(maxVisible, 1), items.length)
57
58 const maxStart = Math.max(items.length - visibleCount, 0)
59 const idealStart = clampedSelected - Math.floor((visibleCount - 1) / 2)
60 const start = Math.max(0, Math.min(idealStart, maxStart))
61 const visibleItems = items.slice(start, start + visibleCount)
62
63 // Calculate max label length for alignment
64 const maxLabelLength = Math.max(
65 ...visibleItems.map(
66 (item) => effectivePrefix.length + item.label.length,
67 ),
68 )
69
70 // Find the longest description to determine if we can use same-line layout
71 const maxDescriptionLength = Math.max(
72 ...visibleItems.map((item) => item.description.length),
73 )
74
75 // Check if all items can fit on same line with aligned descriptions
76 const minWidthForSameLine = maxLabelLength + 2 + maxDescriptionLength
77 const useSameLine = menuWidth >= minWidthForSameLine
78
79 const renderSuggestionItem = (item: SuggestionItem, idx: number) => {
80 const absoluteIndex = start + idx
81 const isSelected = absoluteIndex === clampedSelected

Callers

nothing calls this directly

Calls 2

useThemeFunction · 0.90
useTerminalDimensionsFunction · 0.90

Tested by

no test coverage detected