Skip to content

Commit b8c867f

Browse files
Refactor branch item UI with bordered containers and merged headers
Completely redesigned the visual presentation of agent and tool call blocks: - Replace corner characters with proper OpenTUI bordered containers - Merge header into border when expanded for cleaner appearance - Add collapsible footer with "collapse" text for better UX - Refactor nested content rendering into reusable functions - Consistently filter hidden tools (spawn_agent_inline, end_turn, spawn_agents) - Optimize hidden tools check using Set instead of Array The new design provides clearer visual boundaries and reduces clutter while maintaining full functionality. 🤖 Generated with Codebuff Co-Authored-By: Codebuff <noreply@codebuff.com>
1 parent 1672137 commit b8c867f

File tree

3 files changed

+369
-208
lines changed

3 files changed

+369
-208
lines changed

cli/src/components/branch-item.tsx

Lines changed: 99 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,20 @@ interface BranchItemProps {
1515
onToggle: () => void
1616
}
1717

18+
const BRANCH_BORDER_CHARS = {
19+
topLeft: '┌',
20+
topRight: '┐',
21+
bottomLeft: '└',
22+
bottomRight: '┘',
23+
horizontal: '─',
24+
vertical: '│',
25+
topT: '┬',
26+
bottomT: '┴',
27+
leftT: '├',
28+
rightT: '┤',
29+
cross: '┼',
30+
} as const
31+
1832
export const BranchItem = ({
1933
name,
2034
content,
@@ -28,6 +42,8 @@ export const BranchItem = ({
2842
}: BranchItemProps) => {
2943
const indentPrefix = branchChar ? branchChar.replace(/./g, ' ') : ''
3044
const cornerColor = theme.agentPrefix
45+
const shouldMergeHeader = !isCollapsed && !!content
46+
const outerPaddingRight = branchChar ? 1 : 0
3147

3248
const isTextRenderable = (value: ReactNode): boolean => {
3349
if (
@@ -116,40 +132,52 @@ export const BranchItem = ({
116132
}
117133

118134
return (
119-
<box style={{ flexDirection: 'row', flexShrink: 0 }}>
135+
<box
136+
style={{
137+
flexDirection: 'row',
138+
flexShrink: 0,
139+
paddingRight: outerPaddingRight,
140+
}}
141+
>
120142
<text wrap={false}>{indentPrefix}</text>
121143
<box
122144
style={{
123145
flexDirection: 'column',
124146
gap: 0,
125147
flexShrink: 1,
126148
flexGrow: 1,
149+
marginTop: isCollapsed ? 1 : 0,
150+
marginBottom: isCollapsed ? 1 : 0,
127151
}}
128152
>
129-
<box
130-
style={{
131-
flexDirection: 'row',
132-
alignSelf: 'flex-start',
133-
backgroundColor: isCollapsed
134-
? theme.agentResponseCount
135-
: theme.agentPrefix,
136-
paddingLeft: 1,
137-
paddingRight: 1,
138-
}}
139-
onMouseDown={onToggle}
140-
>
141-
<text wrap>
142-
<span fg={theme.agentToggleText}>
143-
{isCollapsed ? '▸ ' : '▾ '}
144-
</span>
145-
<span
146-
fg={theme.agentToggleText}
147-
attributes={TextAttributes.BOLD}
148-
>
149-
{name}
150-
</span>
151-
</text>
152-
</box>
153+
{!shouldMergeHeader && (
154+
<box
155+
style={{
156+
flexDirection: 'row',
157+
alignSelf: 'flex-start',
158+
backgroundColor: isCollapsed
159+
? theme.agentResponseCount
160+
: theme.agentPrefix,
161+
paddingLeft: 4,
162+
paddingRight: 4,
163+
paddingTop: 0,
164+
paddingBottom: 0,
165+
}}
166+
onMouseDown={onToggle}
167+
>
168+
<text wrap>
169+
<span fg={theme.agentToggleText}>
170+
{isCollapsed ? '▸ ' : '▾ '}
171+
</span>
172+
<span
173+
fg={theme.agentToggleText}
174+
attributes={TextAttributes.BOLD}
175+
>
176+
{name}
177+
</span>
178+
</text>
179+
</box>
180+
)}
153181
<box style={{ flexShrink: 1, marginBottom: 0 }}>
154182
{isStreaming && isCollapsed && streamingPreview && (
155183
<text
@@ -172,55 +200,62 @@ export const BranchItem = ({
172200
</text>
173201
)}
174202
{!isCollapsed && content && (
175-
<box style={{ flexDirection: 'column', gap: 0 }}>
176-
<box
177-
style={{
178-
flexDirection: 'row',
179-
justifyContent: 'space-between',
180-
}}
181-
>
182-
<text wrap={false} fg={cornerColor}>
183-
184-
</text>
185-
<text wrap={false} fg={cornerColor}>
186-
187-
</text>
188-
</box>
203+
<box style={{ flexDirection: 'column', gap: 0, marginTop: 1 }}>
189204
<box
190205
style={{
191-
flexDirection: 'row',
192-
alignItems: 'stretch',
206+
flexDirection: 'column',
207+
gap: 0,
208+
width: '100%',
209+
border: ['top', 'left', 'right', 'bottom'],
210+
customBorderChars: BRANCH_BORDER_CHARS,
211+
borderColor: cornerColor,
212+
paddingLeft: 1,
213+
paddingRight: 2,
214+
paddingTop: 1,
215+
paddingBottom: 1,
193216
}}
194217
>
195-
<text wrap={false} fg={cornerColor}>
196-
197-
</text>
198-
<box
199-
style={{
200-
flexDirection: 'column',
201-
gap: 0,
202-
flexGrow: 1,
203-
marginLeft: 1,
204-
marginRight: 1,
205-
}}
206-
>
207-
{renderExpandedContent(content)}
208-
</box>
209-
<text wrap={false} fg={cornerColor}>
210-
211-
</text>
218+
{shouldMergeHeader && (
219+
<box
220+
style={{
221+
flexDirection: 'row',
222+
alignItems: 'center',
223+
justifyContent: 'flex-start',
224+
backgroundColor: theme.agentPrefix,
225+
paddingLeft: 4,
226+
paddingRight: 4,
227+
paddingTop: 0,
228+
paddingBottom: 0,
229+
marginBottom: 1,
230+
width: '100%',
231+
}}
232+
onMouseDown={onToggle}
233+
>
234+
<text wrap>
235+
<span fg={theme.agentToggleText}>{'▾ '}</span>
236+
<span
237+
fg={theme.agentToggleText}
238+
attributes={TextAttributes.BOLD}
239+
>
240+
{name}
241+
</span>
242+
</text>
243+
</box>
244+
)}
245+
{renderExpandedContent(content)}
212246
</box>
213247
<box
214248
style={{
215249
flexDirection: 'row',
216-
justifyContent: 'space-between',
250+
alignItems: 'center',
251+
marginTop: 0,
252+
paddingLeft: 1,
253+
paddingRight: 2,
217254
}}
255+
onMouseDown={onToggle}
218256
>
219-
<text wrap={false} fg={cornerColor}>
220-
221-
</text>
222-
<text wrap={false} fg={cornerColor}>
223-
257+
<text fg={theme.agentToggleText} attributes={TextAttributes.DIM}>
258+
collapse
224259
</text>
225260
</box>
226261
</box>

0 commit comments

Comments
 (0)