1- import React , { useCallback } from 'react'
1+ import React , { useCallback , useState } from 'react'
2+ import { TextAttributes } from '@opentui/core'
23
34import { Button } from '../button'
45import { defineToolComponent } from './types'
@@ -22,43 +23,66 @@ const FollowupCard = ({
2223 onSendFollowup,
2324} : FollowupCardProps ) => {
2425 const theme = useTheme ( )
26+ const [ isHovered , setIsHovered ] = useState ( false )
2527
2628 const handleClick = useCallback ( ( ) => {
2729 onSendFollowup ( followup . prompt , index )
2830 } , [ followup . prompt , index , onSendFollowup ] )
2931
30- // Use label if provided, otherwise truncate the prompt
31- const displayLabel = followup . label || truncateText ( followup . prompt , 40 )
32+ const handleMouseOver = useCallback ( ( ) => setIsHovered ( true ) , [ ] )
33+ const handleMouseOut = useCallback ( ( ) => setIsHovered ( false ) , [ ] )
34+
35+ const hasLabel = Boolean ( followup . label )
36+
37+ // Determine colors based on state
38+ const borderColor = isClicked
39+ ? theme . success
40+ : isHovered
41+ ? theme . primary
42+ : theme . border
43+ const labelColor = isClicked ? theme . muted : theme . secondary
44+ const promptColor = isClicked ? theme . muted : theme . foreground
3245
3346 return (
3447 < Button
3548 onClick = { handleClick }
49+ onMouseOver = { handleMouseOver }
50+ onMouseOut = { handleMouseOut }
3651 style = { {
3752 paddingLeft : 2 ,
3853 paddingRight : 2 ,
3954 paddingTop : 0 ,
4055 paddingBottom : 0 ,
41- backgroundColor : isClicked ? theme . surface : theme . surfaceHover ,
42- borderColor : isClicked ? theme . success : theme . border ,
56+ maxWidth : 40 ,
57+ borderColor,
58+ flexGrow : 1 ,
4359 } }
4460 >
45- < text
46- style = { {
47- fg : isClicked ? theme . muted : theme . foreground ,
48- } }
49- >
50- { isClicked && < span fg = { theme . success } > ✓ </ span > }
51- < span > { displayLabel } </ span >
52- </ text >
61+ < box style = { { flexDirection : 'column' } } >
62+ { hasLabel && (
63+ < text
64+ style = { {
65+ fg : labelColor ,
66+ } }
67+ attributes = { TextAttributes . BOLD }
68+ >
69+ { isClicked ? < span fg = { theme . success } > ✓ </ span > : < span > → </ span > }
70+ < span > { followup . label } </ span >
71+ </ text >
72+ ) }
73+ < text
74+ style = { {
75+ fg : promptColor ,
76+ } }
77+ >
78+ { ! hasLabel && isClicked && < span fg = { theme . success } > ✓ </ span > }
79+ < span > { followup . prompt } </ span >
80+ </ text >
81+ </ box >
5382 </ Button >
5483 )
5584}
5685
57- function truncateText ( text : string , maxLength : number ) : string {
58- if ( text . length <= maxLength ) return text
59- return text . slice ( 0 , maxLength - 1 ) + '…'
60- }
61-
6286interface SuggestFollowupsItemProps {
6387 toolCallId : string
6488 followups : SuggestedFollowup [ ]
@@ -80,14 +104,19 @@ const SuggestFollowupsItem = ({
80104 : new Set < number > ( )
81105
82106 return (
83- < box style = { { flexDirection : 'column' , gap : 1 , width : '100%' } } >
84- < text style = { { fg : theme . muted } } > Suggested next steps:</ text >
107+ < box
108+ style = { {
109+ flexDirection : 'column' ,
110+ gap : 1 ,
111+ } }
112+ >
113+ < text style = { { fg : theme . primary } } attributes = { TextAttributes . BOLD } >
114+ Suggested next steps:
115+ </ text >
85116 < box
86117 style = { {
87118 flexDirection : 'row' ,
88- gap : 1 ,
89119 flexWrap : 'wrap' ,
90- width : '100%' ,
91120 } }
92121 >
93122 { followups . map ( ( followup , index ) => (
0 commit comments