assistant2: Polish the thinking card (#27363)

Mostly just adjusting spacing and making it consistent with how we
display other tool calls.

<img
src="https://github.com/user-attachments/assets/85892006-9029-4cb8-b805-bebe4232e458"
width="600px" />

Release Notes:

- N/A
This commit is contained in:
Danilo Leal 2025-03-24 10:08:49 -03:00 committed by GitHub
parent 4e33aaa55c
commit 7db9077835
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -752,7 +752,7 @@ impl ActiveThread {
let editor_bg_color = colors.editor_background; let editor_bg_color = colors.editor_background;
let bg_user_message_header = editor_bg_color.blend(active_color.opacity(0.25)); let bg_user_message_header = editor_bg_color.blend(active_color.opacity(0.25));
let feedback_container = h_flex().pb_4().px_4().gap_1().justify_between(); let feedback_container = h_flex().pt_2().pb_4().px_4().gap_1().justify_between();
let feedback_items = match self.thread.read(cx).feedback() { let feedback_items = match self.thread.read(cx).feedback() {
Some(feedback) => feedback_container Some(feedback) => feedback_container
.child( .child(
@ -1001,6 +1001,7 @@ impl ActiveThread {
.id(("message-container", ix)) .id(("message-container", ix))
.ml_2() .ml_2()
.pl_2() .pl_2()
.pr_4()
.border_l_1() .border_l_1()
.border_color(cx.theme().colors().border_variant) .border_color(cx.theme().colors().border_variant)
.child(message_content) .child(message_content)
@ -1169,129 +1170,148 @@ impl ActiveThread {
let lighter_border = cx.theme().colors().border.opacity(0.5); let lighter_border = cx.theme().colors().border.opacity(0.5);
let editor_bg = cx.theme().colors().editor_background; let editor_bg = cx.theme().colors().editor_background;
v_flex() div().py_2().child(
.rounded_lg() v_flex()
.border_1() .rounded_lg()
.border_color(lighter_border) .border_1()
.child( .border_color(lighter_border)
h_flex() .child(
.justify_between() h_flex()
.py_1() .group("disclosure-header")
.pl_1() .justify_between()
.pr_2() .py_1()
.bg(cx.theme().colors().editor_foreground.opacity(0.025)) .px_2()
.map(|this| { .bg(cx.theme().colors().editor_foreground.opacity(0.025))
if is_open { .map(|this| {
this.rounded_t_md() if pending || is_open {
.border_b_1() this.rounded_t_md()
.border_color(lighter_border) .border_b_1()
} else { .border_color(lighter_border)
this.rounded_md() } else {
} this.rounded_md()
}) }
.child( })
h_flex() .child(
.gap_1() h_flex()
.child(Disclosure::new("thinking-disclosure", is_open).on_click( .gap_1p5()
cx.listener({ .child(
move |this, _event, _window, _cx| { Icon::new(IconName::Brain)
let is_open = this .size(IconSize::XSmall)
.expanded_thinking_segments .color(Color::Muted),
.entry((message_id, ix)) )
.or_insert(false); .child({
if pending {
*is_open = !*is_open; Label::new("Thinking…")
.size(LabelSize::Small)
.buffer_font(cx)
.with_animation(
"pulsating-label",
Animation::new(Duration::from_secs(2))
.repeat()
.with_easing(pulsating_between(0.4, 0.8)),
|label, delta| label.alpha(delta),
)
.into_any_element()
} else {
Label::new("Thought Process")
.size(LabelSize::Small)
.buffer_font(cx)
.into_any_element()
} }
}), }),
)) )
.child({ .child(
if pending { h_flex()
Label::new("Thinking…") .gap_1()
.size(LabelSize::Small) .child(
.buffer_font(cx) div().visible_on_hover("disclosure-header").child(
.with_animation( Disclosure::new("thinking-disclosure", is_open)
"pulsating-label", .opened_icon(IconName::ChevronUp)
Animation::new(Duration::from_secs(2)) .closed_icon(IconName::ChevronDown)
.repeat() .on_click(cx.listener({
.with_easing(pulsating_between(0.4, 0.8)), move |this, _event, _window, _cx| {
|label, delta| label.alpha(delta), let is_open = this
.expanded_thinking_segments
.entry((message_id, ix))
.or_insert(false);
*is_open = !*is_open;
}
})),
),
)
.child({
let (icon_name, color, animated) = if pending {
(IconName::ArrowCircle, Color::Accent, true)
} else {
(IconName::Check, Color::Success, false)
};
let icon =
Icon::new(icon_name).color(color).size(IconSize::Small);
if animated {
icon.with_animation(
"arrow-circle",
Animation::new(Duration::from_secs(2)).repeat(),
|icon, delta| {
icon.transform(Transformation::rotate(percentage(
delta,
)))
},
) )
.into_any_element() .into_any_element()
} else { } else {
Label::new("Thought Process") icon.into_any_element()
.size(LabelSize::Small) }
.buffer_font(cx) }),
.into_any_element() ),
} )
}), .when(pending && !is_open, |this| {
) let gradient_overlay = div()
.child({ .rounded_b_lg()
let (icon_name, color, animated) = if pending { .h_20()
(IconName::ArrowCircle, Color::Accent, true) .absolute()
} else { .w_full()
(IconName::Check, Color::Success, false) .bottom_0()
}; .left_0()
.bg(linear_gradient(
180.,
linear_color_stop(editor_bg, 1.),
linear_color_stop(editor_bg.opacity(0.2), 0.),
));
let icon = Icon::new(icon_name).color(color).size(IconSize::Small); this.child(
div()
if animated { .relative()
icon.with_animation( .bg(editor_bg)
"arrow-circle", .rounded_b_lg()
Animation::new(Duration::from_secs(2)).repeat(), .child(
|icon, delta| { div()
icon.transform(Transformation::rotate(percentage(delta))) .id(("thinking-content", ix))
}, .p_2()
.h_20()
.track_scroll(scroll_handle)
.text_ui_sm(cx)
.child(markdown.clone())
.overflow_hidden(),
) )
.into_any_element() .child(gradient_overlay),
} else { )
icon.into_any_element() })
} .when(is_open, |this| {
}), this.child(
) div()
.when(pending && !is_open, |this| { .id(("thinking-content", ix))
let gradient_overlay = div() .h_full()
.rounded_b_lg() .p_2()
.h_20() .rounded_b_lg()
.absolute() .bg(editor_bg)
.w_full() .text_ui_sm(cx)
.bottom_0() .child(markdown.clone()),
.left_0() )
.bg(linear_gradient( }),
180., )
linear_color_stop(editor_bg, 1.),
linear_color_stop(editor_bg.opacity(0.2), 0.),
));
this.child(
div()
.relative()
.bg(editor_bg)
.rounded_b_lg()
.text_ui_sm(cx)
.child(
div()
.id(("thinking-content", ix))
.p_2()
.h_20()
.track_scroll(scroll_handle)
.child(markdown.clone())
.overflow_hidden(),
)
.child(gradient_overlay),
)
})
.when(is_open, |this| {
this.child(
div()
.id(("thinking-content", ix))
.h_full()
.p_2()
.rounded_b_lg()
.bg(editor_bg)
.text_ui_sm(cx)
.child(markdown.clone()),
)
})
} }
fn render_tool_use(&self, tool_use: ToolUse, cx: &mut Context<Self>) -> impl IntoElement { fn render_tool_use(&self, tool_use: ToolUse, cx: &mut Context<Self>) -> impl IntoElement {
@ -1318,7 +1338,7 @@ impl ActiveThread {
_ => IconName::Terminal, _ => IconName::Terminal,
}; };
div().py_2().pr_4().child( div().py_2().child(
v_flex() v_flex()
.rounded_lg() .rounded_lg()
.border_1() .border_1()