1- import React , { useState } from 'react'
1+ import React , { useRef , useState } from 'react'
22import stringWidth from 'string-width'
33import { useTheme } from '../hooks/use-theme'
44
@@ -38,6 +38,7 @@ export const AgentModeToggle = ({
3838 const theme = useTheme ( )
3939 const config = getModeConfig ( theme )
4040 const [ isOpen , setIsOpen ] = useState ( false )
41+ const closeTimeoutRef = useRef < NodeJS . Timeout | null > ( null )
4142
4243 const handlePress = ( selectedMode : AgentMode ) => {
4344 if ( selectedMode === mode ) {
@@ -54,11 +55,28 @@ export const AgentModeToggle = ({
5455 }
5556 }
5657
58+ const handleMouseOver = ( ) => {
59+ // Cancel any pending close
60+ if ( closeTimeoutRef . current ) {
61+ clearTimeout ( closeTimeoutRef . current )
62+ closeTimeoutRef . current = null
63+ }
64+ setIsOpen ( true )
65+ }
66+
67+ const handleMouseOut = ( ) => {
68+ // Delay closing by 1 second
69+ closeTimeoutRef . current = setTimeout ( ( ) => {
70+ setIsOpen ( false )
71+ closeTimeoutRef . current = null
72+ } , 1000 )
73+ }
74+
5775 if ( ! isOpen ) {
5876 // Collapsed state: show only current mode
5977 const { frameColor, textColor, label } = config [ mode ]
60- const arrow = ' < '
61- const contentText = ` ${ label } ${ arrow } `
78+ const arrow = '< '
79+ const contentText = ` ${ arrow } ${ label } `
6280 const contentWidth = stringWidth ( contentText )
6381 const horizontal = '─' . repeat ( contentWidth )
6482
@@ -70,13 +88,19 @@ export const AgentModeToggle = ({
7088 backgroundColor : 'transparent' ,
7189 } }
7290 onMouseDown = { ( ) => handlePress ( mode ) }
91+ onMouseOver = { handleMouseOver }
92+ onMouseOut = { handleMouseOut }
7393 >
7494 < text >
7595 < span fg = { frameColor } > { `╭${ horizontal } ╮` } </ span >
7696 </ text >
7797 < text >
7898 < span fg = { frameColor } > │</ span >
79- < span fg = { textColor } > { contentText } </ span >
99+ < span fg = { textColor } > { arrow } </ span >
100+ < b >
101+ < span fg = { textColor } > { label } </ span >
102+ </ b >
103+ < span fg = { textColor } > </ span >
80104 < span fg = { frameColor } > │</ span >
81105 </ text >
82106 < text >
@@ -97,7 +121,7 @@ export const AgentModeToggle = ({
97121 const label = config [ m ] . label
98122 if ( m === mode ) {
99123 // Active mode shows label with collapse arrow
100- return stringWidth ( ` ${ label } > ` )
124+ return stringWidth ( ` < ${ label } ` )
101125 }
102126 return stringWidth ( ` ${ label } ` )
103127 } )
@@ -110,15 +134,18 @@ export const AgentModeToggle = ({
110134 const { frameColor, textColor, label } = config [ modeItem ]
111135 const isActive = modeItem === mode
112136 const width = segmentWidths [ index ]
113- const content = isActive ? ` ${ label } > ` : ` ${ label } `
137+ const content = isActive ? ` < ${ label } ` : ` ${ label } `
114138 const horizontal = '─' . repeat ( width )
115139
116140 return {
117- topBorder : isLast ? ` ${ horizontal } ╮` : ` ${ horizontal } ┬` ,
141+ topBorder : horizontal ,
118142 content,
119- bottomBorder : isLast ? ` ${ horizontal } ╯` : ` ${ horizontal } ┴` ,
143+ bottomBorder : horizontal ,
120144 frameColor,
121145 textColor,
146+ isActive,
147+ label,
148+ width,
122149 }
123150 }
124151
@@ -129,57 +156,75 @@ export const AgentModeToggle = ({
129156 return (
130157 < box
131158 style = { {
132- flexDirection : 'column ' ,
159+ flexDirection : 'row ' ,
133160 gap : 0 ,
134161 backgroundColor : 'transparent' ,
135162 } }
163+ onMouseOver = { handleMouseOver }
164+ onMouseOut = { handleMouseOut }
136165 >
137- { /* Top border */ }
138- < text >
139- < span fg = { segments [ 0 ] . frameColor } > ╭</ span >
140- { segments . map ( ( seg , idx ) => (
141- < span key = { `top-${ idx } ` } fg = { seg . frameColor } >
142- { seg . topBorder }
143- </ span >
144- ) ) }
145- </ text >
146-
147- { /* Content row with clickable segments */ }
148- < box
149- style = { {
150- flexDirection : 'row' ,
151- gap : 0 ,
152- } }
153- >
166+ { /* Left edge */ }
167+ < box style = { { flexDirection : 'column' , gap : 0 } } >
168+ < text >
169+ < span fg = { segments [ 0 ] . frameColor } > ╭</ span >
170+ </ text >
154171 < text >
155172 < span fg = { segments [ 0 ] . frameColor } > │</ span >
156173 </ text >
157- { segments . map ( ( seg , idx ) => {
158- const modeItem = orderedModes [ idx ]
159- return (
160- < React . Fragment key = { `content-${ idx } ` } >
161- < box onMouseDown = { ( ) => handlePress ( modeItem ) } >
162- < text >
174+ < text >
175+ < span fg = { segments [ 0 ] . frameColor } > ╰</ span >
176+ </ text >
177+ </ box >
178+
179+ { /* Segments as vertical columns */ }
180+ { segments . map ( ( seg , idx ) => {
181+ const modeItem = orderedModes [ idx ]
182+ const isLast = idx === segments . length - 1
183+ return (
184+ < React . Fragment key = { `segment-${ idx } ` } >
185+ < box
186+ onMouseDown = { ( ) => handlePress ( modeItem ) }
187+ style = { {
188+ flexDirection : 'column' ,
189+ gap : 0 ,
190+ width : seg . width ,
191+ minWidth : seg . width ,
192+ } }
193+ >
194+ < text >
195+ < span fg = { seg . frameColor } > { seg . topBorder } </ span >
196+ </ text >
197+ < text >
198+ { seg . isActive ? (
199+ < >
200+ < span fg = { seg . textColor } > { '< ' } </ span >
201+ < b >
202+ < span fg = { seg . textColor } > { seg . label } </ span >
203+ </ b >
204+ < span fg = { seg . textColor } > </ span >
205+ </ >
206+ ) : (
163207 < span fg = { seg . textColor } > { seg . content } </ span >
164- </ text >
165- </ box >
208+ ) }
209+ </ text >
210+ < text >
211+ < span fg = { seg . frameColor } > { seg . bottomBorder } </ span >
212+ </ text >
213+ </ box >
214+ < box style = { { flexDirection : 'column' , gap : 0 } } >
215+ < text >
216+ < span fg = { seg . frameColor } > { isLast ? '╮' : '┬' } </ span >
217+ </ text >
166218 < text >
167219 < span fg = { seg . frameColor } > │</ span >
168220 </ text >
169- </ React . Fragment >
170- )
171- } ) }
172- </ box >
173-
174- { /* Bottom border */ }
175- < text >
176- < span fg = { segments [ 0 ] . frameColor } > ╰</ span >
177- { segments . map ( ( seg , idx ) => (
178- < span key = { `bottom-${ idx } ` } fg = { seg . frameColor } >
179- { seg . bottomBorder }
180- </ span >
181- ) ) }
182- </ text >
221+ < text >
222+ < span fg = { seg . frameColor } > { isLast ? '╯' : '┴' } </ span >
223+ </ text >
224+ </ box >
225+ </ React . Fragment >
226+ )
227+ } ) }
183228 </ box >
184229 )
185230}
0 commit comments