Add adjustments to agent v2 pane changes (#44885)

Danilo Leal created

Follow-up to https://github.com/zed-industries/zed/pull/44190.

Release Notes:

- N/A

Change summary

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(-)

Detailed changes

assets/icons/zed_agent_two.svg 🔗

@@ -0,0 +1,5 @@
+<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M6.2224 1.32129L5.2036 4.41875C5.15145 4.57727 5.06282 4.72134 4.94481 4.83934C4.82681 4.95735 4.68274 5.04598 4.52422 5.09813L1.42676 6.11693L4.52422 7.13574C4.68274 7.18788 4.82681 7.27652 4.94481 7.39453C5.06282 7.51253 5.15145 7.6566 5.2036 7.81512L6.2224 10.9126L7.24121 7.81512C7.29335 7.6566 7.38199 7.51253 7.5 7.39453C7.618 7.27652 7.76207 7.18788 7.9206 7.13574L11.018 6.11693L7.9206 5.09813C7.76207 5.04598 7.618 4.95735 7.5 4.83934C7.38199 4.72134 7.29335 4.57727 7.24121 4.41875L6.2224 1.32129Z" fill="black" fill-opacity="0.15" stroke="black" stroke-width="1.2" stroke-linecap="round" stroke-linejoin="round"/>
+<path d="M9.76681 13.9373C9.76681 13.6048 9.95997 13.3083 10.5126 12.7917L11.8872 11.4978C12.3545 11.0575 12.5612 10.77 12.5612 10.4735C12.5612 10.1411 12.3185 9.91643 11.9681 9.91643C11.6986 9.91643 11.5054 10.0242 11.2673 10.3208C10.9933 10.6622 10.7956 10.779 10.4946 10.779C10.0633 10.779 9.75781 10.4915 9.75781 10.0916C9.75781 9.21559 10.8136 8.44287 12.067 8.44287C13.3743 8.44287 14.3492 9.22907 14.3492 10.2848C14.3492 10.9452 13.9988 11.5742 13.2845 12.2077L12.2242 13.1511V13.223H13.7292C14.2503 13.223 14.5738 13.5015 14.5738 13.9552C14.5738 14.4089 14.2593 14.6785 13.7292 14.6785H10.5979C10.1037 14.6785 9.76681 14.3775 9.76681 13.9373Z" fill="black"/>
+<path d="M12.8994 1.32129V4.00482M11.5576 2.66302H14.2412" stroke="black" stroke-opacity="0.75" stroke-width="1.2" stroke-linecap="round" stroke-linejoin="round"/>
+</svg>

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<Workspace>, 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<Self>| {
-            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<Workspace>| {
+            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()
+                            })),
+                    ),
+            )
     }
 }
 

crates/agent_ui_v2/src/agents_panel.rs 🔗

@@ -411,7 +411,7 @@ impl Panel for AgentsPanel {
     }
 
     fn icon(&self, _window: &Window, cx: &App) -> Option<IconName> {
-        (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> {

crates/icons/src/icons.rs 🔗

@@ -260,6 +260,7 @@ pub enum IconName {
     XCircle,
     XCircleFilled,
     ZedAgent,
+    ZedAgentTwo,
     ZedAssistant,
     ZedBurnMode,
     ZedBurnModeOn,

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))

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!"