sidebar: Click project header row to toggle fold instead of switching worktrees (#53861)

Nathan Sobo created

Previously, clicking a project header in the agent sidebar would
activate/switch to that worktree's workspace, resuming whatever thread
was most recently active. This felt jarring — activating a random thread
based on recency isn't that useful when the user can just click the
specific thread they want. There's also no clear semantic for clicking
the overall group header since each thread maps to a specific workspace
and there's no single workspace to activate for the group.

This changes the click target for folding from just the chevron to the
entire header row. The worktree-switching behavior is removed — clicking
anywhere on the row now toggles the fold, which is a more predictable
and useful interaction.

The hover-only buttons on the right side (ellipsis menu, collapse
threads, new thread) continue to work as before, with their own click
handlers that stop propagation.

Release Notes:

- Improved sidebar project headers to toggle fold on click instead of
switching worktrees.

Change summary

crates/sidebar/src/sidebar.rs | 37 +++++++------------------------------
1 file changed, 7 insertions(+), 30 deletions(-)

Detailed changes

crates/sidebar/src/sidebar.rs 🔗

@@ -1806,9 +1806,6 @@ impl Sidebar {
                             move |this, _, window, cx| {
                                 this.set_group_expanded(&key, true, cx);
                                 this.selection = None;
-                                // If the active workspace belongs to this
-                                // group, use it (preserves linked worktree
-                                // context). Otherwise resolve from the key.
                                 let workspace = this.multi_workspace.upgrade().and_then(|mw| {
                                     let mw = mw.read(cx);
                                     let active = mw.workspace().clone();
@@ -1832,33 +1829,13 @@ impl Sidebar {
                         ))
                     }),
             )
-            .map(|this| {
-                if !has_threads && is_active {
-                    this
-                } else {
-                    let key = key.clone();
-                    this.cursor_pointer()
-                        .when(!is_active, |this| this.hover(|s| s.bg(hover_solid)))
-                        .tooltip(Tooltip::text("Open Workspace"))
-                        .on_click(cx.listener(move |this, _, window, cx| {
-                            if let Some(workspace) = this.multi_workspace.upgrade().and_then(|mw| {
-                                mw.read(cx).workspace_for_paths(
-                                    key.path_list(),
-                                    key.host().as_ref(),
-                                    cx,
-                                )
-                            }) {
-                                // Just activate the workspace. The
-                                // AgentPanel remembers what was last
-                                // shown, so the user returns to whatever
-                                // thread/draft they were looking at.
-                                this.activate_workspace(&workspace, window, cx);
-                            } else {
-                                this.open_workspace_for_group(&key, window, cx);
-                            }
-                        }))
-                }
-            })
+            .cursor_pointer()
+            .when(!is_active, |this| this.hover(|s| s.bg(hover_solid)))
+            .tooltip(Tooltip::text(disclosure_tooltip))
+            .on_click(cx.listener(move |this, _, window, cx| {
+                this.selection = None;
+                this.toggle_collapse(&key_for_collapse, window, cx);
+            }))
             .into_any_element()
     }