Add clear filter button to outline and collab panels' search (#46210)

Danilo Leal created

Always missed the ability to clear the search without having to reach
for my keyboard if I'm on a mouse-first workflow:

<img width="460" height="390" alt="Screenshot 2026-01-06 at 9  27@2x"
src="https://github.com/user-attachments/assets/fda4650c-72fb-4b5b-92f6-7c69661507f8"
/>

Release Notes:

- Added a button to clear the search query for the collab and outline
panels' search bar.

Change summary

crates/collab_ui/src/collab_panel.rs      | 21 ++++++++++++--
crates/outline_panel/src/outline_panel.rs | 34 ++++++++++++++++++++----
2 files changed, 45 insertions(+), 10 deletions(-)

Detailed changes

crates/collab_ui/src/collab_panel.rs 🔗

@@ -31,9 +31,8 @@ use smallvec::SmallVec;
 use std::{mem, sync::Arc};
 use theme::{ActiveTheme, ThemeSettings};
 use ui::{
-    Avatar, AvatarAvailabilityIndicator, Button, Color, ContextMenu, CopyButton, Facepile,
-    HighlightedLabel, Icon, IconButton, IconName, IconSize, Indicator, Label, ListHeader, ListItem,
-    Tab, Tooltip, prelude::*, tooltip_container,
+    Avatar, AvatarAvailabilityIndicator, ContextMenu, CopyButton, Facepile, HighlightedLabel,
+    IconButtonShape, Indicator, ListHeader, ListItem, Tab, Tooltip, prelude::*, tooltip_container,
 };
 use util::{ResultExt, TryFutureExt, maybe};
 use workspace::{
@@ -2422,6 +2421,9 @@ impl CollabPanel {
         self.channel_store.update(cx, |channel_store, _| {
             channel_store.initialize();
         });
+
+        let has_query = !self.filter_editor.read(cx).text(cx).is_empty();
+
         v_flex()
             .size_full()
             .gap_1()
@@ -2437,7 +2439,18 @@ impl CollabPanel {
                             .size(IconSize::Small)
                             .color(Color::Muted),
                     )
-                    .child(self.render_filter_input(&self.filter_editor, cx)),
+                    .child(self.render_filter_input(&self.filter_editor, cx))
+                    .when(has_query, |this| {
+                        this.pr_2p5().child(
+                            IconButton::new("clear_filter", IconName::Close)
+                                .shape(IconButtonShape::Square)
+                                .tooltip(Tooltip::text("Clear Filter"))
+                                .on_click(cx.listener(|this, _, window, cx| {
+                                    this.reset_filter_editor_text(window, cx);
+                                    cx.notify();
+                                })),
+                        )
+                    }),
             )
             .child(
                 list(

crates/outline_panel/src/outline_panel.rs 🔗

@@ -4799,6 +4799,8 @@ impl OutlinePanel {
             (IconName::Pin, "Pin Active Outline")
         };
 
+        let has_query = self.query(cx).is_some();
+
         h_flex()
             .p_2()
             .h(Tab::container_height(cx))
@@ -4817,12 +4819,32 @@ impl OutlinePanel {
                     .child(self.filter_editor.clone()),
             )
             .child(
-                IconButton::new("pin_button", icon)
-                    .tooltip(Tooltip::text(icon_tooltip))
-                    .shape(IconButtonShape::Square)
-                    .on_click(cx.listener(|outline_panel, _, window, cx| {
-                        outline_panel.toggle_active_editor_pin(&ToggleActiveEditorPin, window, cx);
-                    })),
+                h_flex()
+                    .when(has_query, |this| {
+                        this.child(
+                            IconButton::new("clear_filter", IconName::Close)
+                                .shape(IconButtonShape::Square)
+                                .tooltip(Tooltip::text("Clear Filter"))
+                                .on_click(cx.listener(|outline_panel, _, window, cx| {
+                                    outline_panel.filter_editor.update(cx, |editor, cx| {
+                                        editor.set_text("", window, cx);
+                                    });
+                                    cx.notify();
+                                })),
+                        )
+                    })
+                    .child(
+                        IconButton::new("pin_button", icon)
+                            .tooltip(Tooltip::text(icon_tooltip))
+                            .shape(IconButtonShape::Square)
+                            .on_click(cx.listener(|outline_panel, _, window, cx| {
+                                outline_panel.toggle_active_editor_pin(
+                                    &ToggleActiveEditorPin,
+                                    window,
+                                    cx,
+                                );
+                            })),
+                    ),
             )
     }