From f2f3d9faf6f22aa4995f2df045286068b693d5c2 Mon Sep 17 00:00:00 2001
From: Danilo Leal <67129314+danilo-leal@users.noreply.github.com>
Date: Mon, 15 Dec 2025 13:02:01 -0300
Subject: [PATCH] Add adjustments to agent v2 pane changes (#44885)
Follow-up to https://github.com/zed-industries/zed/pull/44190.
Release Notes:
- N/A
---
assets/icons/zed_agent_two.svg | 5 ++
crates/agent_ui_v2/src/agent_thread_pane.rs | 99 ++++++++++-----------
crates/agent_ui_v2/src/agents_panel.rs | 2 +-
crates/icons/src/icons.rs | 1 +
crates/ui/src/components/tab_bar.rs | 1 +
crates/workspace/src/pane.rs | 74 ++++++++++-----
6 files changed, 107 insertions(+), 75 deletions(-)
create mode 100644 assets/icons/zed_agent_two.svg
diff --git a/assets/icons/zed_agent_two.svg b/assets/icons/zed_agent_two.svg
new file mode 100644
index 0000000000000000000000000000000000000000..c352be84d2f1bea6da1f6a5be70b9420f019b6d6
--- /dev/null
+++ b/assets/icons/zed_agent_two.svg
@@ -0,0 +1,5 @@
+
diff --git a/crates/agent_ui_v2/src/agent_thread_pane.rs b/crates/agent_ui_v2/src/agent_thread_pane.rs
index cfe861ef09c51af511554b3d15a1c810a793ed15..72886f87eca38c630ec29b9b410930f1d3936b50 100644
--- a/crates/agent_ui_v2/src/agent_thread_pane.rs
+++ b/crates/agent_ui_v2/src/agent_thread_pane.rs
@@ -13,13 +13,12 @@ use settings::DockSide;
use settings::Settings as _;
use std::rc::Rc;
use std::sync::Arc;
-use ui::{
- App, Clickable as _, Context, DynamicSpacing, IconButton, IconName, IconSize, IntoElement,
- Label, LabelCommon as _, LabelSize, Render, Tab, Window, div,
+use ui::{Tab, Tooltip, prelude::*};
+use workspace::{
+ Workspace,
+ dock::{ClosePane, MinimizePane, UtilityPane, UtilityPanePosition},
+ utility_pane::UtilityPaneSlot,
};
-use workspace::Workspace;
-use workspace::dock::{ClosePane, MinimizePane, UtilityPane, UtilityPanePosition};
-use workspace::utility_pane::UtilityPaneSlot;
pub const DEFAULT_UTILITY_PANE_WIDTH: Pixels = gpui::px(400.0);
@@ -169,58 +168,56 @@ impl AgentThreadPane {
let toggle_icon = self.toggle_icon(cx);
let title = self.title(cx);
- let make_toggle_button = |workspace: WeakEntity, cx: &App| {
- div().px(DynamicSpacing::Base06.rems(cx)).child(
- IconButton::new("toggle_utility_pane", toggle_icon)
- .icon_size(IconSize::Small)
- .on_click(move |_, window, cx| {
- workspace
- .update(cx, |workspace, cx| {
- workspace.toggle_utility_pane(slot, window, cx)
- })
- .ok();
- }),
- )
- };
-
- let make_close_button = |id: &'static str, cx: &mut Context| {
- let on_click = cx.listener(|this, _: &gpui::ClickEvent, _window, cx| {
- cx.emit(ClosePane);
- this.thread_view = None;
- cx.notify();
- });
- div().px(DynamicSpacing::Base06.rems(cx)).child(
- IconButton::new(id, IconName::Close)
- .icon_size(IconSize::Small)
- .on_click(on_click),
- )
- };
-
- let make_title_label = |title: SharedString, cx: &App| {
- div()
- .px(DynamicSpacing::Base06.rems(cx))
- .child(Label::new(title).size(LabelSize::Small))
+ let pane_toggle_button = |workspace: WeakEntity| {
+ IconButton::new("toggle_utility_pane", toggle_icon)
+ .icon_size(IconSize::Small)
+ .tooltip(Tooltip::text("Toggle Agent Pane"))
+ .on_click(move |_, window, cx| {
+ workspace
+ .update(cx, |workspace, cx| {
+ workspace.toggle_utility_pane(slot, window, cx)
+ })
+ .ok();
+ })
};
- div()
+ h_flex()
.id("utility-pane-header")
- .flex()
- .flex_none()
- .items_center()
.w_full()
.h(Tab::container_height(cx))
- .when(slot == UtilityPaneSlot::Left, |this| {
- this.child(make_toggle_button(workspace.clone(), cx))
- .child(make_title_label(title.clone(), cx))
- .child(div().flex_grow())
- .child(make_close_button("close_utility_pane_left", cx))
- })
+ .px_1p5()
+ .gap(DynamicSpacing::Base06.rems(cx))
.when(slot == UtilityPaneSlot::Right, |this| {
- this.child(make_close_button("close_utility_pane_right", cx))
- .child(make_title_label(title.clone(), cx))
- .child(div().flex_grow())
- .child(make_toggle_button(workspace.clone(), cx))
+ this.flex_row_reverse()
})
+ .flex_none()
+ .border_b_1()
+ .border_color(cx.theme().colors().border)
+ .child(pane_toggle_button(workspace))
+ .child(
+ h_flex()
+ .size_full()
+ .min_w_0()
+ .gap_1()
+ .map(|this| {
+ if slot == UtilityPaneSlot::Right {
+ this.flex_row_reverse().justify_start()
+ } else {
+ this.justify_between()
+ }
+ })
+ .child(Label::new(title).truncate())
+ .child(
+ IconButton::new("close_btn", IconName::Close)
+ .icon_size(IconSize::Small)
+ .tooltip(Tooltip::text("Close Agent Pane"))
+ .on_click(cx.listener(|this, _: &gpui::ClickEvent, _window, cx| {
+ cx.emit(ClosePane);
+ this.thread_view = None;
+ cx.notify()
+ })),
+ ),
+ )
}
}
diff --git a/crates/agent_ui_v2/src/agents_panel.rs b/crates/agent_ui_v2/src/agents_panel.rs
index ace5e73f56b9eff4292f34263bfe08a94e2d6050..a7afdddda43514ade40b7fd9dfd8bcd8ace33dc7 100644
--- a/crates/agent_ui_v2/src/agents_panel.rs
+++ b/crates/agent_ui_v2/src/agents_panel.rs
@@ -411,7 +411,7 @@ impl Panel for AgentsPanel {
}
fn icon(&self, _window: &Window, cx: &App) -> Option {
- (self.enabled(cx) && AgentSettings::get_global(cx).button).then_some(IconName::ZedAgent)
+ (self.enabled(cx) && AgentSettings::get_global(cx).button).then_some(IconName::ZedAgentTwo)
}
fn icon_tooltip(&self, _window: &Window, _cx: &App) -> Option<&'static str> {
diff --git a/crates/icons/src/icons.rs b/crates/icons/src/icons.rs
index bf4c74f984ff4aa8f06d6408957eddabcf5f94ed..23ae7a6d928d98aafe48d28cfe5626bbf76d29b8 100644
--- a/crates/icons/src/icons.rs
+++ b/crates/icons/src/icons.rs
@@ -260,6 +260,7 @@ pub enum IconName {
XCircle,
XCircleFilled,
ZedAgent,
+ ZedAgentTwo,
ZedAssistant,
ZedBurnMode,
ZedBurnModeOn,
diff --git a/crates/ui/src/components/tab_bar.rs b/crates/ui/src/components/tab_bar.rs
index 681f9a726e0d5f4796325a4533fca909617f1e08..86598b8c6f1ab3a479313c7775405863e9e3b49b 100644
--- a/crates/ui/src/components/tab_bar.rs
+++ b/crates/ui/src/components/tab_bar.rs
@@ -162,6 +162,7 @@ impl RenderOnce for TabBar {
.when(!self.end_children.is_empty(), |div| {
div.child(
h_flex()
+ .h_full()
.flex_none()
.pl(DynamicSpacing::Base04.rems(cx))
.gap(DynamicSpacing::Base04.rems(cx))
diff --git a/crates/workspace/src/pane.rs b/crates/workspace/src/pane.rs
index ee57f06937ee2781e8d1b965b5e498f5a31ad80d..50ba58926ece8818ac5a4f44103c3b86eb2b672d 100644
--- a/crates/workspace/src/pane.rs
+++ b/crates/workspace/src/pane.rs
@@ -3047,6 +3047,8 @@ impl Pane {
};
let focus_handle = self.focus_handle.clone();
+ let is_pane_focused = self.has_focus(window, cx);
+
let navigate_backward = IconButton::new("navigate_backward", IconName::ArrowLeft)
.icon_size(IconSize::Small)
.on_click({
@@ -3076,15 +3078,27 @@ impl Pane {
let toggle_icon = pane.toggle_icon(cx);
let workspace_handle = self.workspace.clone();
- IconButton::new("open_aside_left", toggle_icon)
- .icon_size(IconSize::Small)
- .on_click(move |_, window, cx| {
- workspace_handle
- .update(cx, |workspace, cx| {
- workspace.toggle_utility_pane(UtilityPaneSlot::Left, window, cx)
- })
- .ok();
- })
+ h_flex()
+ .h_full()
+ .pr_1p5()
+ .border_r_1()
+ .border_color(cx.theme().colors().border)
+ .child(
+ IconButton::new("open_aside_left", toggle_icon)
+ .icon_size(IconSize::Small)
+ .tooltip(Tooltip::text("Toggle Agent Pane")) // TODO: Probably want to make this generic
+ .on_click(move |_, window, cx| {
+ workspace_handle
+ .update(cx, |workspace, cx| {
+ workspace.toggle_utility_pane(
+ UtilityPaneSlot::Left,
+ window,
+ cx,
+ )
+ })
+ .ok();
+ }),
+ )
.into_any_element()
})
};
@@ -3095,15 +3109,29 @@ impl Pane {
let toggle_icon = pane.toggle_icon(cx);
let workspace_handle = self.workspace.clone();
- IconButton::new("open_aside_right", toggle_icon)
- .icon_size(IconSize::Small)
- .on_click(move |_, window, cx| {
- workspace_handle
- .update(cx, |workspace, cx| {
- workspace.toggle_utility_pane(UtilityPaneSlot::Right, window, cx)
- })
- .ok();
+ h_flex()
+ .h_full()
+ .when(is_pane_focused, |this| {
+ this.pl(DynamicSpacing::Base04.rems(cx))
+ .border_l_1()
+ .border_color(cx.theme().colors().border)
})
+ .child(
+ IconButton::new("open_aside_right", toggle_icon)
+ .icon_size(IconSize::Small)
+ .tooltip(Tooltip::text("Toggle Agent Pane")) // TODO: Probably want to make this generic
+ .on_click(move |_, window, cx| {
+ workspace_handle
+ .update(cx, |workspace, cx| {
+ workspace.toggle_utility_pane(
+ UtilityPaneSlot::Right,
+ window,
+ cx,
+ )
+ })
+ .ok();
+ }),
+ )
.into_any_element()
})
};
@@ -3196,8 +3224,8 @@ impl Pane {
self.display_nav_history_buttons.unwrap_or_default(),
|tab_bar| {
tab_bar
- .pre_end_child(navigate_backward)
- .pre_end_child(navigate_forward)
+ .start_child(navigate_backward)
+ .start_child(navigate_forward)
},
)
.map(|tab_bar| {
@@ -6756,13 +6784,13 @@ mod tests {
let tab_bar_scroll_handle =
pane.update_in(cx, |pane, _window, _cx| pane.tab_bar_scroll_handle.clone());
assert_eq!(tab_bar_scroll_handle.children_count(), 6);
- let tab_bounds = cx.debug_bounds("TAB-3").unwrap();
+ let tab_bounds = cx.debug_bounds("TAB-4").unwrap();
let new_tab_button_bounds = cx.debug_bounds("ICON-Plus").unwrap();
let scroll_bounds = tab_bar_scroll_handle.bounds();
let scroll_offset = tab_bar_scroll_handle.offset();
- assert!(tab_bounds.right() <= scroll_bounds.right() + scroll_offset.x);
- // -35.0 is the magic number for this setup
- assert_eq!(scroll_offset.x, px(-35.0));
+ assert!(tab_bounds.right() <= scroll_bounds.right());
+ // -43.0 is the magic number for this setup
+ assert_eq!(scroll_offset.x, px(-43.0));
assert!(
!tab_bounds.intersects(&new_tab_button_bounds),
"Tab should not overlap with the new tab button, if this is failing check if there's been a redesign!"