From 1764337a5d314bc771e6847319bb00bd894652de Mon Sep 17 00:00:00 2001
From: Danilo Leal <67129314+danilo-leal@users.noreply.github.com>
Date: Mon, 6 Oct 2025 11:40:01 -0300
Subject: [PATCH] agent: Fix plan summary text overflow in Claude Code threads
(#39603)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
| Before | After |
|--------|--------|
|
|
|
Release Notes:
- agent: Fixed a bug in Claude Code threads where the plan summary text
would overflow beyond its container.
---
crates/agent_ui/src/acp/thread_view.rs | 87 +++++++++++++++-----------
1 file changed, 52 insertions(+), 35 deletions(-)
diff --git a/crates/agent_ui/src/acp/thread_view.rs b/crates/agent_ui/src/acp/thread_view.rs
index c29d0fac1a454ed181b63cd2ba405a0e743869e5..c086ab75bef40a82b655242cc330a7569a724f44 100644
--- a/crates/agent_ui/src/acp/thread_view.rs
+++ b/crates/agent_ui/src/acp/thread_view.rs
@@ -26,7 +26,7 @@ use gpui::{
CursorStyle, EdgesRefinement, ElementId, Empty, Entity, FocusHandle, Focusable, Hsla, Length,
ListOffset, ListState, PlatformDisplay, SharedString, StyleRefinement, Subscription, Task,
TextStyle, TextStyleRefinement, UnderlineStyle, WeakEntity, Window, WindowHandle, div,
- ease_in_out, linear_color_stop, linear_gradient, list, point, prelude::*, pulsating_between,
+ ease_in_out, linear_color_stop, linear_gradient, list, point, pulsating_between,
};
use language::Buffer;
@@ -3388,6 +3388,12 @@ impl AcpThreadView {
.into_any_element()
}
+ fn activity_bar_bg(&self, cx: &Context) -> Hsla {
+ let editor_bg_color = cx.theme().colors().editor_background;
+ let active_color = cx.theme().colors().element_selected;
+ editor_bg_color.blend(active_color.opacity(0.3))
+ }
+
fn render_activity_bar(
&self,
thread_entity: &Entity,
@@ -3403,10 +3409,6 @@ impl AcpThreadView {
return None;
}
- let editor_bg_color = cx.theme().colors().editor_background;
- let active_color = cx.theme().colors().element_selected;
- let bg_edit_files_disclosure = editor_bg_color.blend(active_color.opacity(0.3));
-
// Temporarily always enable ACP edit controls. This is temporary, to lessen the
// impact of a nasty bug that causes them to sometimes be disabled when they shouldn't
// be, which blocks you from being able to accept or reject edits. This switches the
@@ -3417,7 +3419,7 @@ impl AcpThreadView {
v_flex()
.mt_1()
.mx_2()
- .bg(bg_edit_files_disclosure)
+ .bg(self.activity_bar_bg(cx))
.border_1()
.border_b_0()
.border_color(cx.theme().colors().border)
@@ -3458,27 +3460,33 @@ impl AcpThreadView {
.into()
}
- fn render_plan_summary(&self, plan: &Plan, window: &mut Window, cx: &Context) -> Div {
+ fn render_plan_summary(
+ &self,
+ plan: &Plan,
+ window: &mut Window,
+ cx: &Context,
+ ) -> impl IntoElement {
let stats = plan.stats();
let title = if let Some(entry) = stats.in_progress_entry
&& !self.plan_expanded
{
h_flex()
- .w_full()
.cursor_default()
+ .relative()
+ .w_full()
.gap_1()
- .text_xs()
- .text_color(cx.theme().colors().text_muted)
- .justify_between()
+ .truncate()
.child(
- h_flex()
- .gap_1()
- .child(
- Label::new("Current:")
- .size(LabelSize::Small)
- .color(Color::Muted),
- )
+ Label::new("Current:")
+ .size(LabelSize::Small)
+ .color(Color::Muted),
+ )
+ .child(
+ div()
+ .text_xs()
+ .text_color(cx.theme().colors().text_muted)
+ .line_clamp(1)
.child(MarkdownElement::new(
entry.content.clone(),
plan_label_markdown_style(&entry.status, window, cx),
@@ -3486,10 +3494,23 @@ impl AcpThreadView {
)
.when(stats.pending > 0, |this| {
this.child(
- Label::new(format!("{} left", stats.pending))
- .size(LabelSize::Small)
- .color(Color::Muted)
- .mr_1(),
+ h_flex()
+ .absolute()
+ .top_0()
+ .right_0()
+ .h_full()
+ .child(div().min_w_8().h_full().bg(linear_gradient(
+ 90.,
+ linear_color_stop(self.activity_bar_bg(cx), 1.),
+ linear_color_stop(self.activity_bar_bg(cx).opacity(0.2), 0.),
+ )))
+ .child(
+ div().pr_0p5().bg(self.activity_bar_bg(cx)).child(
+ Label::new(format!("{} left", stats.pending))
+ .size(LabelSize::Small)
+ .color(Color::Muted),
+ ),
+ ),
)
})
} else {
@@ -3519,23 +3540,19 @@ impl AcpThreadView {
};
h_flex()
+ .id("plan_summary")
.p_1()
- .justify_between()
+ .w_full()
+ .gap_1()
.when(self.plan_expanded, |this| {
this.border_b_1().border_color(cx.theme().colors().border)
})
- .child(
- h_flex()
- .id("plan_summary")
- .w_full()
- .gap_1()
- .child(Disclosure::new("plan_disclosure", self.plan_expanded))
- .child(title)
- .on_click(cx.listener(|this, _, _, cx| {
- this.plan_expanded = !this.plan_expanded;
- cx.notify();
- })),
- )
+ .child(Disclosure::new("plan_disclosure", self.plan_expanded))
+ .child(title)
+ .on_click(cx.listener(|this, _, _, cx| {
+ this.plan_expanded = !this.plan_expanded;
+ cx.notify();
+ }))
}
fn render_plan_entries(&self, plan: &Plan, window: &mut Window, cx: &Context) -> Div {