diff --git a/crates/search/src/project_search.rs b/crates/search/src/project_search.rs index b018f29693..0edc38a095 100644 --- a/crates/search/src/project_search.rs +++ b/crates/search/src/project_search.rs @@ -34,8 +34,8 @@ use std::{ }; use theme::ThemeSettings; use ui::{ - h_flex, prelude::*, v_flex, Icon, IconButton, IconName, KeyBinding, Label, LabelCommon, - LabelSize, Selectable, Tooltip, + h_flex, prelude::*, v_flex, Icon, IconButton, IconButtonShape, IconName, KeyBinding, Label, + LabelCommon, LabelSize, Selectable, Tooltip, }; use util::paths::PathMatcher; use workspace::{ @@ -45,9 +45,6 @@ use workspace::{ ToolbarItemView, Workspace, WorkspaceId, }; -const MIN_INPUT_WIDTH_REMS: f32 = 15.; -const MAX_INPUT_WIDTH_REMS: f32 = 30.; - actions!( project_search, [SearchInNew, ToggleFocus, NextField, ToggleFilters] @@ -669,7 +666,7 @@ impl ProjectSearchView { let query_editor = cx.new_view(|cx| { let mut editor = Editor::single_line(cx); - editor.set_placeholder_text("Search all files..", cx); + editor.set_placeholder_text("Search all files...", cx); editor.set_text(query_text, cx); editor }); @@ -692,7 +689,7 @@ impl ProjectSearchView { ); let replacement_editor = cx.new_view(|cx| { let mut editor = Editor::single_line(cx); - editor.set_placeholder_text("Replace in project..", cx); + editor.set_placeholder_text("Replace in project...", cx); if let Some(text) = replacement_text { editor.set_text(text, cx); } @@ -1167,7 +1164,11 @@ impl ProjectSearchView { let focus_handle = self.focus_handle.clone(); v_flex() .gap_1() - .child(Label::new("Hit enter to search. For more options:")) + .child( + Label::new("Hit enter to search. For more options:") + .color(Color::Muted) + .mb_2(), + ) .child( Button::new("filter-paths", "Include/exclude specific paths") .icon(IconName::Filter) @@ -1555,23 +1556,25 @@ impl Render for ProjectSearchBar { let search = search.read(cx); let focus_handle = search.focus_handle(cx); - let query_column = h_flex() - .flex_1() - .h_8() - .mr_2() - .px_2() - .py_1() - .border_1() - .border_color(search.border_color_for(InputPanel::Query, cx)) - .rounded_lg() - .min_w(rems(MIN_INPUT_WIDTH_REMS)) - .max_w(rems(MAX_INPUT_WIDTH_REMS)) + let input_base_styles = || { + h_flex() + .w_full() + .h_8() + .px_2() + .py_1() + .border_1() + .border_color(search.border_color_for(InputPanel::Query, cx)) + .rounded_lg() + }; + + let query_column = input_base_styles() .on_action(cx.listener(|this, action, cx| this.confirm(action, cx))) .on_action(cx.listener(|this, action, cx| this.previous_history_query(action, cx))) .on_action(cx.listener(|this, action, cx| this.next_history_query(action, cx))) .child(self.render_text_input(&search.query_editor, cx)) .child( h_flex() + .gap_0p5() .child(SearchOptions::CASE_SENSITIVE.as_button( self.is_option_enabled(SearchOptions::CASE_SENSITIVE, cx), focus_handle.clone(), @@ -1595,58 +1598,60 @@ impl Render for ProjectSearchBar { )), ); - let mode_column = v_flex().items_start().justify_start().child( - h_flex() - .child( - IconButton::new("project-search-filter-button", IconName::Filter) - .tooltip(|cx| Tooltip::for_action("Toggle filters", &ToggleFilters, cx)) - .on_click(cx.listener(|this, _, cx| { - this.toggle_filters(cx); - })) - .selected( - self.active_project_search - .as_ref() - .map(|search| search.read(cx).filters_enabled) - .unwrap_or_default(), - ) - .tooltip({ - let focus_handle = focus_handle.clone(); - move |cx| { - Tooltip::for_action_in( - "Toggle filters", - &ToggleFilters, - &focus_handle, - cx, - ) - } - }), - ) - .child( - IconButton::new("project-search-toggle-replace", IconName::Replace) - .on_click(cx.listener(|this, _, cx| { - this.toggle_replace(&ToggleReplace, cx); - })) - .selected( - self.active_project_search - .as_ref() - .map(|search| search.read(cx).replace_enabled) - .unwrap_or_default(), - ) - .tooltip({ - let focus_handle = focus_handle.clone(); - move |cx| { - Tooltip::for_action_in( - "Toggle Replace", - &ToggleReplace, - &focus_handle, - cx, - ) - } - }), - ), - ); + let mode_column = h_flex() + .gap_1() + .child( + IconButton::new("project-search-filter-button", IconName::Filter) + .shape(IconButtonShape::Square) + .tooltip(|cx| Tooltip::for_action("Toggle Filters", &ToggleFilters, cx)) + .on_click(cx.listener(|this, _, cx| { + this.toggle_filters(cx); + })) + .selected( + self.active_project_search + .as_ref() + .map(|search| search.read(cx).filters_enabled) + .unwrap_or_default(), + ) + .tooltip({ + let focus_handle = focus_handle.clone(); + move |cx| { + Tooltip::for_action_in( + "Toggle Filters", + &ToggleFilters, + &focus_handle, + cx, + ) + } + }), + ) + .child( + IconButton::new("project-search-toggle-replace", IconName::Replace) + .shape(IconButtonShape::Square) + .on_click(cx.listener(|this, _, cx| { + this.toggle_replace(&ToggleReplace, cx); + })) + .selected( + self.active_project_search + .as_ref() + .map(|search| search.read(cx).replace_enabled) + .unwrap_or_default(), + ) + .tooltip({ + let focus_handle = focus_handle.clone(); + move |cx| { + Tooltip::for_action_in( + "Toggle Replace", + &ToggleReplace, + &focus_handle, + cx, + ) + } + }), + ); let limit_reached = search.model.read(cx).limit_reached; + let match_text = search .active_match_index .and_then(|index| { @@ -1668,6 +1673,7 @@ impl Render for ProjectSearchBar { let matches_column = h_flex() .child( IconButton::new("project-search-prev-match", IconName::ChevronLeft) + .shape(IconButtonShape::Square) .disabled(search.active_match_index.is_none()) .on_click(cx.listener(|this, _, cx| { if let Some(search) = this.active_project_search.as_ref() { @@ -1680,7 +1686,7 @@ impl Render for ProjectSearchBar { let focus_handle = focus_handle.clone(); move |cx| { Tooltip::for_action_in( - "Go to previous match", + "Go To Previous Match", &SelectPrevMatch, &focus_handle, cx, @@ -1690,6 +1696,7 @@ impl Render for ProjectSearchBar { ) .child( IconButton::new("project-search-next-match", IconName::ChevronRight) + .shape(IconButtonShape::Square) .disabled(search.active_match_index.is_none()) .on_click(cx.listener(|this, _, cx| { if let Some(search) = this.active_project_search.as_ref() { @@ -1702,7 +1709,7 @@ impl Render for ProjectSearchBar { let focus_handle = focus_handle.clone(); move |cx| { Tooltip::for_action_in( - "Go to next match", + "Go To Next Match", &SelectNextMatch, &focus_handle, cx, @@ -1711,9 +1718,9 @@ impl Render for ProjectSearchBar { }), ) .child( - h_flex() + div() .id("matches") - .min_w(rems_from_px(40.)) + .ml_0p5() .child( Label::new(match_text).color(if search.active_match_index.is_some() { Color::Default @@ -1729,27 +1736,23 @@ impl Render for ProjectSearchBar { ); let search_line = h_flex() - .flex_1() + .w_full() + .gap_1p5() + .pr_6() .child(query_column) .child(mode_column) .child(matches_column); let replace_line = search.replace_enabled.then(|| { - let replace_column = h_flex() - .flex_1() - .min_w(rems(MIN_INPUT_WIDTH_REMS)) - .max_w(rems(MAX_INPUT_WIDTH_REMS)) - .h_8() - .px_2() - .py_1() - .border_1() - .border_color(cx.theme().colors().border) - .rounded_lg() - .child(self.render_text_input(&search.replacement_editor, cx)); + let replace_column = + input_base_styles().child(self.render_text_input(&search.replacement_editor, cx)); + let focus_handle = search.replacement_editor.read(cx).focus_handle(cx); - let replace_actions = h_flex().when(search.replace_enabled, |this| { + + let replace_actions = h_flex().gap_1().when(search.replace_enabled, |this| { this.child( IconButton::new("project-search-replace-next", IconName::ReplaceNext) + .shape(IconButtonShape::Square) .on_click(cx.listener(|this, _, cx| { if let Some(search) = this.active_project_search.as_ref() { search.update(cx, |this, cx| { @@ -1761,7 +1764,7 @@ impl Render for ProjectSearchBar { let focus_handle = focus_handle.clone(); move |cx| { Tooltip::for_action_in( - "Replace next match", + "Replace Next Match", &ReplaceNext, &focus_handle, cx, @@ -1771,6 +1774,7 @@ impl Render for ProjectSearchBar { ) .child( IconButton::new("project-search-replace-all", IconName::ReplaceAll) + .shape(IconButtonShape::Square) .on_click(cx.listener(|this, _, cx| { if let Some(search) = this.active_project_search.as_ref() { search.update(cx, |this, cx| { @@ -1782,7 +1786,7 @@ impl Render for ProjectSearchBar { let focus_handle = focus_handle.clone(); move |cx| { Tooltip::for_action_in( - "Replace all matches", + "Replace All Matches", &ReplaceAll, &focus_handle, cx, @@ -1791,9 +1795,11 @@ impl Render for ProjectSearchBar { }), ) }); + h_flex() - .pr(rems(5.5)) - .gap_2() + .w_full() + .gap_1p5() + .pr_24() .child(replace_column) .child(replace_actions) }); @@ -1801,20 +1807,10 @@ impl Render for ProjectSearchBar { let filter_line = search.filters_enabled.then(|| { h_flex() .w_full() - .gap_2() + .gap_1p5() + .pr_24() .child( - h_flex() - .flex_1() - // chosen so the total width of the search bar line - // is about the same as the include/exclude line - .min_w(rems(10.25)) - .max_w(rems(20.)) - .h_8() - .px_2() - .py_1() - .border_1() - .border_color(search.border_color_for(InputPanel::Include, cx)) - .rounded_lg() + input_base_styles() .on_action( cx.listener(|this, action, cx| this.previous_history_query(action, cx)), ) @@ -1824,16 +1820,7 @@ impl Render for ProjectSearchBar { .child(self.render_text_input(&search.included_files_editor, cx)), ) .child( - h_flex() - .flex_1() - .min_w(rems(10.25)) - .max_w(rems(20.)) - .h_8() - .px_2() - .py_1() - .border_1() - .border_color(search.border_color_for(InputPanel::Exclude, cx)) - .rounded_lg() + input_base_styles() .on_action( cx.listener(|this, action, cx| this.previous_history_query(action, cx)), ) @@ -1843,27 +1830,35 @@ impl Render for ProjectSearchBar { .child(self.render_text_input(&search.excluded_files_editor, cx)), ) .child( - IconButton::new("project-search-opened-only", IconName::FileDoc) - .selected(self.is_opened_only_enabled(cx)) - .tooltip(|cx| Tooltip::text("Only search open files", cx)) - .on_click(cx.listener(|this, _, cx| { - this.toggle_opened_only(cx); - })), - ) - .child( - SearchOptions::INCLUDE_IGNORED.as_button( - search - .search_options - .contains(SearchOptions::INCLUDE_IGNORED), - focus_handle.clone(), - cx.listener(|this, _, cx| { - this.toggle_search_option(SearchOptions::INCLUDE_IGNORED, cx); - }), - ), + h_flex() + .gap_1() + .child( + IconButton::new("project-search-opened-only", IconName::FileDoc) + .shape(IconButtonShape::Square) + .selected(self.is_opened_only_enabled(cx)) + .tooltip(|cx| Tooltip::text("Only Search Open Files", cx)) + .on_click(cx.listener(|this, _, cx| { + this.toggle_opened_only(cx); + })), + ) + .child( + SearchOptions::INCLUDE_IGNORED.as_button( + search + .search_options + .contains(SearchOptions::INCLUDE_IGNORED), + focus_handle.clone(), + cx.listener(|this, _, cx| { + this.toggle_search_option(SearchOptions::INCLUDE_IGNORED, cx); + }), + ), + ), ) }); + let mut key_context = KeyContext::default(); + key_context.add("ProjectSearchBar"); + if search.replacement_editor.focus_handle(cx).is_focused(cx) { key_context.add("in_replace"); }