Skip to content

Commit ce238e8

Browse files
committed
Tweak collapsing tool blocks
1 parent 2d0aa6e commit ce238e8

File tree

1 file changed

+89
-55
lines changed

1 file changed

+89
-55
lines changed

crates/code_assistant/src/ui/gpui/elements.rs

Lines changed: 89 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ use gpui::{
66
IntoElement, MouseButton, SharedString, Styled, Transformation,
77
};
88
use gpui::{prelude::*, FontWeight};
9-
use gpui_component::{scroll::ScrollbarAxis, ActiveTheme, StyledExt};
9+
use gpui_component::{label::Label, ActiveTheme};
1010
use std::sync::{Arc, Mutex};
1111
use std::time::Duration;
1212
use tracing::trace;
@@ -82,7 +82,7 @@ impl MessageContainer {
8282
status: ToolStatus::Pending,
8383
status_message: None,
8484
output: None,
85-
is_collapsed: true, // Default to collapsed
85+
is_collapsed: false, // Default to expanded
8686
});
8787
let view = cx.new(|cx| BlockView::new(block, cx));
8888
elements.push(view);
@@ -105,12 +105,15 @@ impl MessageContainer {
105105
element.update(cx, |view, cx| {
106106
if let Some(tool) = view.block.as_tool_mut() {
107107
if tool.id == tool_id {
108-
tool.status = status;
108+
tool.status = status.clone();
109109
tool.status_message = message.clone();
110110
tool.output = output.clone();
111111

112-
// Auto-expand failed tool calls
113-
if status == ToolStatus::Error {
112+
// Auto-collapse on completion or error
113+
if status == ToolStatus::Success || status == ToolStatus::Error {
114+
tool.is_collapsed = true;
115+
} else {
116+
// Ensure it's expanded if it's still pending or in progress
114117
tool.is_collapsed = false;
115118
}
116119

@@ -264,7 +267,7 @@ impl MessageContainer {
264267
status: ToolStatus::Pending,
265268
status_message: None,
266269
output: None,
267-
is_collapsed: true, // Default to collapsed
270+
is_collapsed: false, // Default to expanded
268271
};
269272

270273
tool.parameters.push(ParameterBlock {
@@ -695,71 +698,102 @@ impl Render for BlockView {
695698
.into_any(),
696699
);
697700

698-
// Second row: Full-width parameters (if any)
699-
if !fullwidth_params.is_empty() {
700-
elements.push(
701-
div()
702-
.flex()
703-
.flex_col()
704-
.w_full()
705-
.mt_1() // Add margin between rows
706-
.children(
707-
fullwidth_params
708-
.iter()
709-
.map(|param| render_parameter(param)),
710-
)
711-
.into_any(),
712-
);
701+
// Conditionally add full-width parameters and output if not collapsed
702+
if !block.is_collapsed {
703+
// Full-width parameters
704+
if !fullwidth_params.is_empty() {
705+
elements.push(
706+
div()
707+
.flex()
708+
.flex_col()
709+
.w_full()
710+
.mt_1() // Add margin between rows
711+
.children(
712+
fullwidth_params
713+
.iter()
714+
.map(|param| render_parameter(param)),
715+
)
716+
.into_any(),
717+
);
718+
}
719+
720+
// Output
721+
if let Some(output_content) = &block.output {
722+
if !output_content.is_empty() { // Also check if output is not empty
723+
elements.push(
724+
div()
725+
.id(SharedString::from(block.id.clone()))
726+
.p_2()
727+
.mt_1()
728+
.w_full()
729+
.text_color(cx.theme().foreground)
730+
.text_size(px(13.))
731+
.child(output_content.clone())
732+
.into_any(),
733+
);
734+
}
735+
}
713736
}
714737

715-
// Tool output content (only shown when expanded or on error)
716-
// Output (only when expanded)
717-
if !block.is_collapsed && block.output.is_some() {
738+
// Error message (always shown for error status, regardless of collapsed state)
739+
if block.status == crate::ui::ToolStatus::Error
740+
&& block.status_message.is_some()
741+
{
718742
elements.push(
719743
div()
720-
.id(SharedString::from(block.id.clone()))
721-
// .flex()
722-
// .flex_row()
723-
//.items_center()
724-
//.flex_1()
744+
.flex()
745+
.flex_row()
746+
.items_center()
725747
.p_2()
726748
.mt_1()
727-
.w_full()
728-
.max_w_full()
729-
.min_h_0()
730-
.max_h(px(300.)) // Max height
731-
.overflow_scroll()
732-
//.overflow_hidden()
733-
// .scrollable(
734-
// cx.entity().entity_id(),
735-
// ScrollbarAxis::Vertical,
736-
// ) // Make it scrollable
737-
.text_color(cx.theme().foreground)
749+
.text_color(cx.theme().danger.opacity(0.9))
738750
.text_size(px(13.))
739-
.child(block.output.clone().unwrap_or_default())
751+
.child(block.status_message.clone().unwrap_or_default())
740752
.into_any(),
741753
);
742754
}
743-
// Error message (always shown for error status)
744-
else if block.status == crate::ui::ToolStatus::Error
745-
&& block.status_message.is_some()
755+
756+
// Bottom collapse bar (only if expanded and there's content to collapse)
757+
if !block.is_collapsed
758+
&& (!fullwidth_params.is_empty()
759+
|| block.output.as_ref().map_or(false, |o| !o.is_empty()))
746760
{
761+
let (collapse_icon, collapse_text) = (
762+
file_icons::get().get_type_icon(file_icons::CHEVRON_UP),
763+
"Collapse", // Simpler text
764+
);
747765
elements.push(
748766
div()
749767
.flex()
750-
.flex_row()
768+
.justify_center()
751769
.items_center()
752-
.p_2()
770+
.w_full()
771+
.p_1()
753772
.mt_1()
754-
.max_h(px(300.)) // Max height
755-
.scrollable(
756-
cx.entity().entity_id(),
757-
ScrollbarAxis::Vertical,
758-
) // Make it scrollable
759-
.text_color(cx.theme().danger.opacity(0.9))
760-
.text_size(px(13.))
761-
.child(block.status_message.clone().unwrap_or_default())
762-
.into_any(),
773+
.border_t_1()
774+
.border_color(cx.theme().border)
775+
.cursor_pointer()
776+
.hover(|s| s.bg(cx.theme().border.opacity(0.5)))
777+
.on_mouse_up(
778+
MouseButton::Left,
779+
cx.listener(move |view, _event, _window, cx| {
780+
view.toggle_tool_collapsed(cx);
781+
}),
782+
)
783+
.child(
784+
div().flex().items_center().gap_1().children(vec![
785+
file_icons::render_icon(
786+
&collapse_icon,
787+
14.0,
788+
chevron_color, // Use existing chevron_color
789+
"▲",
790+
).into_any(),
791+
Label::new(collapse_text)
792+
.text_color(chevron_color) // Style text consistently
793+
.into_any_element()
794+
])
795+
)
796+
.into_any()
763797
);
764798
}
765799

0 commit comments

Comments
 (0)