@@ -8,10 +8,13 @@ import { Button } from '../button'
88
99import type { ToolRenderConfig } from './types'
1010import type { SuggestedFollowup } from '../../state/chat-store'
11+ import { useTerminalDimensions } from '../../hooks/use-terminal-dimensions'
1112
1213const EMPTY_CLICKED_SET = new Set < number > ( )
1314const MIN_LABEL_COLUMN_WIDTH = 12
1415const MAX_LABEL_COLUMN_WIDTH = 60
16+ /** Minimum terminal width to show the prompt description on hover */
17+ const MIN_WIDTH_FOR_DESCRIPTION = 80
1518
1619interface FollowupLineProps {
1720 followup : SuggestedFollowup
@@ -36,24 +39,36 @@ const FollowupLine = ({
3639 labelColumnWidth,
3740} : FollowupLineProps ) => {
3841 const theme = useTheme ( )
42+ const { terminalWidth } = useTerminalDimensions ( )
3943
4044 const handleClick = useCallback ( ( ) => {
41- if ( isClicked || disabled ) return
45+ if ( disabled ) return
4246 onSendFollowup ( followup . prompt , index )
43- } , [ followup . prompt , index , onSendFollowup , isClicked , disabled ] )
47+ } , [ followup . prompt , index , onSendFollowup , disabled ] )
4448
4549 const handleMouseOver = useCallback ( ( ) => onHover ( index ) , [ onHover , index ] )
4650 const handleMouseOut = useCallback ( ( ) => onHover ( null ) , [ onHover ] )
4751
4852 // Compute effective hover state declaratively
49- // Only show hover effects if actually hovered AND item is interactive
50- const showHoverState = isHovered && ! disabled && ! isClicked
53+ // Show hover effects if actually hovered AND not disabled (clicked items can still be hovered)
54+ const showHoverState = isHovered && ! disabled
5155
5256 const hasLabel = Boolean ( followup . label )
5357 const displayText = hasLabel ? followup . label : followup . prompt
5458
55- // Show description when hovered and has a label
56- const showDescription = showHoverState && hasLabel
59+ // Show description when hovered, has a label, and terminal is wide enough
60+ const showDescription =
61+ showHoverState && hasLabel && terminalWidth >= MIN_WIDTH_FOR_DESCRIPTION
62+
63+ // Calculate truncated prompt with ellipsis only when needed
64+ const truncatedPrompt = showDescription
65+ ? ( ( ) => {
66+ const availableWidth = Math . max ( 0 , terminalWidth - labelColumnWidth - 4 )
67+ return followup . prompt . length > availableWidth
68+ ? followup . prompt . slice ( 0 , availableWidth - 1 ) + '…'
69+ : followup . prompt
70+ } ) ( )
71+ : ''
5772
5873 // Determine colors based on state
5974 // When hovered, use primary color (acid green) for both arrow and title
@@ -99,12 +114,12 @@ const FollowupLine = ({
99114 </ span >
100115 </ text >
101116 </ box >
102- { /* Flexible description column - text wraps within remaining space */ }
117+ { /* Flexible description column - truncated with ellipsis */ }
103118 { showDescription && hasLabel && (
104119 < box style = { { flexGrow : 1 } } >
105- < text style = { { wrapMode : 'word ' } } >
120+ < text style = { { wrapMode : 'none ' } } >
106121 < span fg = { theme . foreground } attributes = { TextAttributes . ITALIC } >
107- { followup . prompt }
122+ { truncatedPrompt }
108123 </ span >
109124 </ text >
110125 </ box >
0 commit comments