From 6213f06e1b01f48ee73ccfee9e3c6cddcd959317 Mon Sep 17 00:00:00 2001 From: Danilo Leal <67129314+danilo-leal@users.noreply.github.com> Date: Sat, 11 Apr 2026 13:30:04 -0300 Subject: [PATCH] agent_ui: Add some general UI fixes (#53696) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A note-worthy thing I'm adding in this PR to fix an agent panel problem is a trait method allowing to set a min-width in panels. I think some of them—if not all—could benefit from it, because there is a certain width these panels can get in that we just can't ensure they will work; things will break. So we either accept that and let the user's common sense understand that, or we don't allow them to reach that state... Surely, a small enough _window_ size can still break things, but then it's out of the realms of solution... Release Notes: - Agent: Fixed multi-line queued messages getting cut-off when the agent panel is in full screen. - Agent: Fixed agent panel getting auto-closed after submitting a queued message when the panel is in full screen. - Agent: Added a min-width to the agent panel, preventing it from reaching a small enough width where it would be essentially unusable. --- crates/agent_ui/src/agent_panel.rs | 8 ++++++++ crates/agent_ui/src/conversation_view/thread_view.rs | 11 ++++++++--- crates/workspace/src/dock.rs | 8 ++++++++ crates/workspace/src/workspace.rs | 4 ++++ 4 files changed, 28 insertions(+), 3 deletions(-) diff --git a/crates/agent_ui/src/agent_panel.rs b/crates/agent_ui/src/agent_panel.rs index 8005445034d0b9339d36cb2d48da516f9c2a9207..9452f02732ba2ed05375d37b7659f2200843b5dd 100644 --- a/crates/agent_ui/src/agent_panel.rs +++ b/crates/agent_ui/src/agent_panel.rs @@ -90,6 +90,7 @@ use zed_actions::{ }; const AGENT_PANEL_KEY: &str = "agent_panel"; +const MIN_PANEL_WIDTH: Pixels = px(300.); const RECENTLY_UPDATED_MENU_LIMIT: usize = 6; const LAST_USED_AGENT_KEY: &str = "agent_panel__last_used_external_agent"; @@ -3546,6 +3547,13 @@ impl Panel for AgentPanel { } } + fn min_size(&self, window: &Window, cx: &App) -> Option { + match self.position(window, cx) { + DockPosition::Left | DockPosition::Right => Some(MIN_PANEL_WIDTH), + DockPosition::Bottom => None, + } + } + fn supports_flexible_size(&self) -> bool { true } diff --git a/crates/agent_ui/src/conversation_view/thread_view.rs b/crates/agent_ui/src/conversation_view/thread_view.rs index 66a211b2f4cf048301da1e7c154d50db191ec15a..a3e36cdafbfbbb82661f69784f779ece8f7fcc8b 100644 --- a/crates/agent_ui/src/conversation_view/thread_view.rs +++ b/crates/agent_ui/src/conversation_view/thread_view.rs @@ -1510,6 +1510,9 @@ impl ThreadView { let Some(queued) = self.remove_from_queue(index, cx) else { return; }; + + self.message_editor.focus_handle(cx).focus(window, cx); + let content = queued.content; let tracked_buffers = queued.tracked_buffers; @@ -2257,12 +2260,14 @@ impl ThreadView { let max_content_width = AgentSettings::get_global(cx).max_content_width; - div() + h_flex() .w_full() - .max_w(max_content_width) - .mx_auto() + .justify_center() .child( v_flex() + .flex_basis(max_content_width) + .flex_shrink() + .flex_grow_0() .mx_2() .bg(self.activity_bar_bg(cx)) .border_1() diff --git a/crates/workspace/src/dock.rs b/crates/workspace/src/dock.rs index e58b4b59100c05085c93993370b85a788fc159ca..81e46b513b4b902aeebb1a912261826c0c4f30dc 100644 --- a/crates/workspace/src/dock.rs +++ b/crates/workspace/src/dock.rs @@ -39,6 +39,9 @@ pub trait Panel: Focusable + EventEmitter + Render + Sized { fn position_is_valid(&self, position: DockPosition) -> bool; fn set_position(&mut self, position: DockPosition, window: &mut Window, cx: &mut Context); fn default_size(&self, window: &Window, cx: &App) -> Pixels; + fn min_size(&self, _window: &Window, _cx: &App) -> Option { + None + } fn initial_size_state(&self, _window: &Window, _cx: &App) -> PanelSizeState { PanelSizeState::default() } @@ -98,6 +101,7 @@ pub trait PanelHandle: Send + Sync { fn remote_id(&self) -> Option; fn pane(&self, cx: &App) -> Option>; fn default_size(&self, window: &Window, cx: &App) -> Pixels; + fn min_size(&self, window: &Window, cx: &App) -> Option; fn initial_size_state(&self, window: &Window, cx: &App) -> PanelSizeState; fn size_state_changed(&self, window: &mut Window, cx: &mut App); fn supports_flexible_size(&self, cx: &App) -> bool; @@ -181,6 +185,10 @@ where self.read(cx).default_size(window, cx) } + fn min_size(&self, window: &Window, cx: &App) -> Option { + self.read(cx).min_size(window, cx) + } + fn initial_size_state(&self, window: &Window, cx: &App) -> PanelSizeState { self.read(cx).initial_size_state(window, cx) } diff --git a/crates/workspace/src/workspace.rs b/crates/workspace/src/workspace.rs index 857db0795bbac8cfe5ee3040971d071c05ed38cd..f9330f07ee3d057f33aa660fd491d2e61642d658 100644 --- a/crates/workspace/src/workspace.rs +++ b/crates/workspace/src/workspace.rs @@ -7457,6 +7457,7 @@ impl Workspace { let dock = dock.read(cx); if let Some(panel) = dock.visible_panel() { let size_state = dock.stored_panel_size_state(panel.as_ref()); + let min_size = panel.min_size(window, cx); if position.axis() == Axis::Horizontal { let use_flexible = panel.has_flexible_size(window, cx); let flex_grow = if use_flexible { @@ -7478,6 +7479,9 @@ impl Workspace { .unwrap_or_else(|| panel.default_size(window, cx)); container = container.w(size); } + if let Some(min) = min_size { + container = container.min_w(min); + } } else { let size = size_state .and_then(|state| state.size)