From 5586fbf288b909ade034488e0953a7e95857a16c Mon Sep 17 00:00:00 2001 From: Danilo Leal <67129314+danilo-leal@users.noreply.github.com> Date: Thu, 12 Mar 2026 17:41:56 -0300 Subject: [PATCH] agent_ui: Add UI refinements to the sidebar and archive view (#51419) Adds a loading state to the archive view and a couple of other tiny UI tweaks to the thread item and such. Release Notes: - N/A --- crates/agent_ui/src/sidebar.rs | 4 +- crates/agent_ui/src/threads_archive_view.rs | 92 ++++++++++++++------- crates/ui/src/components/ai/thread_item.rs | 5 +- 3 files changed, 67 insertions(+), 34 deletions(-) diff --git a/crates/agent_ui/src/sidebar.rs b/crates/agent_ui/src/sidebar.rs index 24c5d5f5e5295a7e25af9f486323a16a2405c8e0..7d7779e75504a93c7923ba26ec87e4fce4bbceb9 100644 --- a/crates/agent_ui/src/sidebar.rs +++ b/crates/agent_ui/src/sidebar.rs @@ -1555,7 +1555,7 @@ impl Sidebar { let id = SharedString::from(format!("view-more-{}", ix)); let (icon, label) = if is_fully_expanded { - (IconName::ListCollapse, "Collapse List") + (IconName::ListCollapse, "Collapse") } else { (IconName::Plus, "View More") }; @@ -1685,7 +1685,7 @@ impl Sidebar { h_flex() .p_1p5() .border_t_1() - .border_color(cx.theme().colors().border) + .border_color(cx.theme().colors().border_variant) .child( Button::new("view-archive", "Archive") .full_width() diff --git a/crates/agent_ui/src/threads_archive_view.rs b/crates/agent_ui/src/threads_archive_view.rs index 8ee0eedbd8702c7901258087af5d149fcf210648..3d7dba591dfa60f7408f9710561863791bcd802b 100644 --- a/crates/agent_ui/src/threads_archive_view.rs +++ b/crates/agent_ui/src/threads_archive_view.rs @@ -15,8 +15,8 @@ use menu::{Confirm, SelectFirst, SelectLast, SelectNext, SelectPrevious}; use project::{AgentServerStore, ExternalAgentServerName}; use theme::ActiveTheme; use ui::{ - ButtonLike, ContextMenu, ContextMenuEntry, HighlightedLabel, ListItem, PopoverMenu, - PopoverMenuHandle, Tab, TintColor, Tooltip, WithScrollbar, prelude::*, + ButtonLike, CommonAnimationExt, ContextMenu, ContextMenuEntry, HighlightedLabel, ListItem, + PopoverMenu, PopoverMenuHandle, Tab, TintColor, Tooltip, WithScrollbar, prelude::*, }; use util::ResultExt as _; use zed_actions::editor::{MoveDown, MoveUp}; @@ -110,6 +110,7 @@ pub struct ThreadsArchiveView { _subscriptions: Vec, selected_agent_menu: PopoverMenuHandle, _refresh_history_task: Task<()>, + is_loading: bool, } impl ThreadsArchiveView { @@ -152,13 +153,20 @@ impl ThreadsArchiveView { _subscriptions: vec![filter_editor_subscription], selected_agent_menu: PopoverMenuHandle::default(), _refresh_history_task: Task::ready(()), + is_loading: true, }; - this.set_selected_agent(Agent::NativeAgent, cx); + this.set_selected_agent(Agent::NativeAgent, window, cx); this } - fn set_selected_agent(&mut self, agent: Agent, cx: &mut Context) { + fn set_selected_agent(&mut self, agent: Agent, window: &mut Window, cx: &mut Context) { self.selected_agent = agent.clone(); + self.is_loading = true; + self.history = None; + self.items.clear(); + self.selection = None; + self.list_state.reset(0); + self.reset_filter_editor_text(window, cx); let server = agent.server(self.fs.clone(), self.thread_store.clone()); let connection = self @@ -184,6 +192,7 @@ impl ThreadsArchiveView { history.refresh_full_history(cx); }); self.history = Some(history); + self.is_loading = false; self.update_items(cx); cx.notify(); } @@ -477,9 +486,9 @@ impl ThreadsArchiveView { .icon_color(Color::Muted) .handler({ let this = this.clone(); - move |_, cx| { + move |window, cx| { this.update(cx, |this, cx| { - this.set_selected_agent(Agent::NativeAgent, cx) + this.set_selected_agent(Agent::NativeAgent, window, cx) }) .ok(); } @@ -537,9 +546,9 @@ impl ThreadsArchiveView { let agent = Agent::Custom { name: item.id.0.clone(), }; - move |_, cx| { + move |window, cx| { this.update(cx, |this, cx| { - this.set_selected_agent(agent.clone(), cx) + this.set_selected_agent(agent.clone(), window, cx) }) .ok(); } @@ -565,7 +574,6 @@ impl ThreadsArchiveView { h_flex() .h(Tab::container_height(cx)) .px_1() - .gap_1p5() .justify_between() .border_b_1() .border_color(cx.theme().colors().border) @@ -610,12 +618,54 @@ impl Render for ThreadsArchiveView { let is_empty = self.items.is_empty(); let has_query = !self.filter_editor.read(cx).text(cx).is_empty(); - let empty_state_container = |label: SharedString| { + let content = if self.is_loading { v_flex() .flex_1() .justify_center() .items_center() - .child(Label::new(label).size(LabelSize::Small).color(Color::Muted)) + .child( + Icon::new(IconName::LoadCircle) + .size(IconSize::Small) + .color(Color::Muted) + .with_rotate_animation(2), + ) + .into_any_element() + } else if is_empty && has_query { + v_flex() + .flex_1() + .justify_center() + .items_center() + .child( + Label::new("No threads match your search.") + .size(LabelSize::Small) + .color(Color::Muted), + ) + .into_any_element() + } else if is_empty { + v_flex() + .flex_1() + .justify_center() + .items_center() + .child( + Label::new("No archived threads yet.") + .size(LabelSize::Small) + .color(Color::Muted), + ) + .into_any_element() + } else { + v_flex() + .flex_1() + .overflow_hidden() + .child( + list( + self.list_state.clone(), + cx.processor(Self::render_list_entry), + ) + .flex_1() + .size_full(), + ) + .vertical_scrollbar_for(&self.list_state, window, cx) + .into_any_element() }; v_flex() @@ -631,24 +681,6 @@ impl Render for ThreadsArchiveView { .size_full() .bg(cx.theme().colors().surface_background) .child(self.render_header(cx)) - .child(if is_empty && has_query { - empty_state_container("No threads match your search.".into()).into_any_element() - } else if is_empty { - empty_state_container("No archived threads yet.".into()).into_any_element() - } else { - v_flex() - .flex_1() - .overflow_hidden() - .child( - list( - self.list_state.clone(), - cx.processor(Self::render_list_entry), - ) - .flex_1() - .size_full(), - ) - .vertical_scrollbar_for(&self.list_state, window, cx) - .into_any_element() - }) + .child(content) } } diff --git a/crates/ui/src/components/ai/thread_item.rs b/crates/ui/src/components/ai/thread_item.rs index 5be91e9d98a1219dcfbbba70a5541ba7b827cfc5..13e1db8f483ea251a6f65b61054c205d040a0d53 100644 --- a/crates/ui/src/components/ai/thread_item.rs +++ b/crates/ui/src/components/ai/thread_item.rs @@ -235,9 +235,9 @@ impl RenderOnce for ThreadItem { let gradient_overlay = GradientFade::new(base_bg, color.element_hover, color.element_active) - .width(px(32.0)) + .width(px(64.0)) .right(px(-10.0)) - .gradient_stop(0.8) + .gradient_stop(0.75) .group_name("thread-item"); let has_diff_stats = self.added.is_some() || self.removed.is_some(); @@ -264,6 +264,7 @@ impl RenderOnce for ThreadItem { .border_color(color.border_focused) }) .hover(|s| s.bg(color.element_hover)) + .active(|s| s.bg(color.element_active)) .on_hover(self.on_hover) .child( h_flex()