added major and minor display text to project search, and fixed icon padding

KCaverly and Piotr created

Co-authored-by: Piotr <piotr@zed.dev>

Change summary

crates/search/src/project_search.rs | 73 +++++++++++++++++++++++++-----
crates/theme/src/theme.rs           |  3 
styles/src/style_tree/search.ts     |  8 ++
3 files changed, 68 insertions(+), 16 deletions(-)

Detailed changes

crates/search/src/project_search.rs 🔗

@@ -120,7 +120,7 @@ struct SemanticSearchState {
 }
 
 // TODO: Update the default search mode to get from config
-#[derive(Clone, Default, PartialEq)]
+#[derive(Copy, Clone, Default, PartialEq)]
 enum SearchMode {
     #[default]
     Text,
@@ -282,29 +282,67 @@ impl View for ProjectSearchView {
             enum Status {}
 
             let theme = theme::current(cx).clone();
-            let text = if model.pending_search.is_some() {
+
+            // If Search is Active -> Major: Searching..., Minor: None
+            // If Semantic -> Major: "Search using Natural Language", Minor: {Status}/n{ex...}/n{ex...}
+            // If Regex -> Major: "Search using Regex", Minor: {ex...}
+            // If Text -> Major: "Text search all files and folders", Minor: {...}
+
+            let current_mode = self.current_mode;
+            let major_text = if model.pending_search.is_some() {
                 Cow::Borrowed("Searching...")
-            } else if let Some(semantic) = &self.semantic {
+            } else {
+                match current_mode {
+                    SearchMode::Text => Cow::Borrowed("Text search all files and folders"),
+                    SearchMode::Semantic => {
+                        Cow::Borrowed("Search all files and folders using Natural Language")
+                    }
+                    SearchMode::Regex => Cow::Borrowed("Regex search all files and folders"),
+                }
+            };
+
+            let semantic_status = if let Some(semantic) = &self.semantic {
                 if semantic.outstanding_file_count > 0 {
-                    Cow::Owned(format!(
-                        "Indexing. {} of {}...",
+                    let dots_count = semantic.outstanding_file_count % 3 + 1;
+                    let dots: String = std::iter::repeat('.').take(dots_count).collect();
+                    format!(
+                        "Indexing. {} of {}{dots}",
                         semantic.file_count - semantic.outstanding_file_count,
                         semantic.file_count
-                    ))
+                    )
                 } else {
-                    Cow::Borrowed("Indexing complete")
+                    "Indexing complete".to_string()
                 }
-            } else if self.query_editor.read(cx).text(cx).is_empty() {
-                Cow::Borrowed("Text search all files and folders")
             } else {
-                Cow::Borrowed("No results")
+                "This is an invalid state".to_string()
+            };
+
+            let minor_text = match current_mode {
+                SearchMode::Semantic => [
+                    semantic_status,
+                    "ex. list all available languages".to_owned(),
+                ],
+                _ => [
+                    "Include/exclude specific paths with the filter option.".to_owned(),
+                    "Matching exact word and/or casing is available too.".to_owned(),
+                ],
             };
 
             MouseEventHandler::<Status, _>::new(0, cx, |_, _| {
                 Flex::column()
                     .with_child(Flex::column().contained().flex(1., true))
                     .with_child(
-                        Label::new(text, theme.search.results_status.clone())
+                        Flex::column()
+                            .align_children_center()
+                            .with_child(Label::new(
+                                major_text,
+                                theme.search.major_results_status.clone(),
+                            ))
+                            .with_children(
+                                minor_text.into_iter().map(|x| {
+                                    Label::new(x, theme.search.minor_results_status.clone())
+                                }),
+                            )
                             .aligned()
                             .top()
                             .contained()
@@ -1060,6 +1098,9 @@ impl ProjectSearchBar {
         if let Some(search_view) = self.active_project_search.as_ref() {
             search_view.update(cx, |search_view, cx| {
                 search_view.search_options.toggle(option);
+                if option.contains(SearchOptions::REGEX) {
+                    search_view.current_mode = SearchMode::Regex;
+                }
                 search_view.semantic = None;
                 search_view.search(cx);
             });
@@ -1096,6 +1137,7 @@ impl ProjectSearchBar {
                 if search_view.semantic.is_some() {
                     search_view.semantic = None;
                 } else if let Some(semantic_index) = SemanticIndex::global(cx) {
+                    search_view.current_mode = SearchMode::Semantic;
                     // TODO: confirm that it's ok to send this project
                     search_view.search_options = SearchOptions::none();
 
@@ -1315,7 +1357,13 @@ impl ProjectSearchBar {
                 .with_style(style.container)
         })
         .on_click(MouseButton::Left, move |_, this, cx| {
-            this.toggle_semantic_search(cx);
+            if let Some(search) = this.active_project_search.as_mut() {
+                search.update(cx, |this, cx| {
+                    this.semantic = None;
+                    this.current_mode = SearchMode::Text;
+                    cx.notify();
+                });
+            }
         })
         .with_cursor_style(CursorStyle::PointingHand)
         .with_tooltip::<NormalSearchTag>(
@@ -1425,7 +1473,6 @@ impl View for ProjectSearchBar {
 
             let search = _search.read(cx);
             let icon_style = theme.search.editor_icon.clone();
-            // "
             let query = Flex::row()
                 .with_child(
                     Svg::for_style(icon_style.icon)

crates/theme/src/theme.rs 🔗

@@ -383,7 +383,8 @@ pub struct Search {
     pub action_button: Interactive<ContainedText>,
     pub match_background: Color,
     pub match_index: ContainedText,
-    pub results_status: TextStyle,
+    pub major_results_status: TextStyle,
+    pub minor_results_status: TextStyle,
     pub dismiss_button: Interactive<IconButton>,
     pub editor_icon: IconStyle,
 }

styles/src/style_tree/search.ts 🔗

@@ -140,9 +140,13 @@ export default function search(): any {
                 right: 6,
             },
         },
-        results_status: {
+        major_results_status: {
             ...text(theme.highest, "mono", "on"),
-            size: 18,
+            size: 15,
+        },
+        minor_results_status: {
+            ...text(theme.highest, "mono", "variant"),
+            size: 13,
         },
         dismiss_button: interactive({
             base: {