Search UI polish (#2904)
This PR polishes the search bar UI, making the layout more dense, and the spacing more consistent with the rest of the app. I've also re-ordered the toolbar items to reflect some of @iamnbutler's original search designs. The items related to the search query are on the left, and the actions that navigate the buffer (next, prev, select all, result count) are on the right.
This commit is contained in:
commit
e7ba5a1edb
15 changed files with 319 additions and 461 deletions
|
@ -88,8 +88,7 @@ impl<V: 'static> Flex<V> {
|
||||||
cx: &mut LayoutContext<V>,
|
cx: &mut LayoutContext<V>,
|
||||||
) {
|
) {
|
||||||
let cross_axis = self.axis.invert();
|
let cross_axis = self.axis.invert();
|
||||||
let last = self.children.len() - 1;
|
for child in self.children.iter_mut() {
|
||||||
for (ix, child) in &mut self.children.iter_mut().enumerate() {
|
|
||||||
if let Some(metadata) = child.metadata::<FlexParentData>() {
|
if let Some(metadata) = child.metadata::<FlexParentData>() {
|
||||||
if let Some((flex, expanded)) = metadata.flex {
|
if let Some((flex, expanded)) = metadata.flex {
|
||||||
if expanded != layout_expanded {
|
if expanded != layout_expanded {
|
||||||
|
@ -101,10 +100,6 @@ impl<V: 'static> Flex<V> {
|
||||||
} else {
|
} else {
|
||||||
let space_per_flex = *remaining_space / *remaining_flex;
|
let space_per_flex = *remaining_space / *remaining_flex;
|
||||||
space_per_flex * flex
|
space_per_flex * flex
|
||||||
} - if ix == 0 || ix == last {
|
|
||||||
self.spacing / 2.
|
|
||||||
} else {
|
|
||||||
self.spacing
|
|
||||||
};
|
};
|
||||||
let child_min = if expanded { child_max } else { 0. };
|
let child_min = if expanded { child_max } else { 0. };
|
||||||
let child_constraint = match self.axis {
|
let child_constraint = match self.axis {
|
||||||
|
@ -144,13 +139,12 @@ impl<V: 'static> Element<V> for Flex<V> {
|
||||||
cx: &mut LayoutContext<V>,
|
cx: &mut LayoutContext<V>,
|
||||||
) -> (Vector2F, Self::LayoutState) {
|
) -> (Vector2F, Self::LayoutState) {
|
||||||
let mut total_flex = None;
|
let mut total_flex = None;
|
||||||
let mut fixed_space = 0.0;
|
let mut fixed_space = self.children.len().saturating_sub(1) as f32 * self.spacing;
|
||||||
let mut contains_float = false;
|
let mut contains_float = false;
|
||||||
|
|
||||||
let cross_axis = self.axis.invert();
|
let cross_axis = self.axis.invert();
|
||||||
let mut cross_axis_max: f32 = 0.0;
|
let mut cross_axis_max: f32 = 0.0;
|
||||||
let last = self.children.len().saturating_sub(1);
|
for child in self.children.iter_mut() {
|
||||||
for (ix, child) in &mut self.children.iter_mut().enumerate() {
|
|
||||||
let metadata = child.metadata::<FlexParentData>();
|
let metadata = child.metadata::<FlexParentData>();
|
||||||
contains_float |= metadata.map_or(false, |metadata| metadata.float);
|
contains_float |= metadata.map_or(false, |metadata| metadata.float);
|
||||||
|
|
||||||
|
@ -168,12 +162,7 @@ impl<V: 'static> Element<V> for Flex<V> {
|
||||||
),
|
),
|
||||||
};
|
};
|
||||||
let size = child.layout(child_constraint, view, cx);
|
let size = child.layout(child_constraint, view, cx);
|
||||||
fixed_space += size.along(self.axis)
|
fixed_space += size.along(self.axis);
|
||||||
+ if ix == 0 || ix == last {
|
|
||||||
self.spacing / 2.
|
|
||||||
} else {
|
|
||||||
self.spacing
|
|
||||||
};
|
|
||||||
cross_axis_max = cross_axis_max.max(size.along(cross_axis));
|
cross_axis_max = cross_axis_max.max(size.along(cross_axis));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -333,8 +322,7 @@ impl<V: 'static> Element<V> for Flex<V> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let last = self.children.len().saturating_sub(1);
|
for child in self.children.iter_mut() {
|
||||||
for (ix, child) in &mut self.children.iter_mut().enumerate() {
|
|
||||||
if remaining_space > 0. {
|
if remaining_space > 0. {
|
||||||
if let Some(metadata) = child.metadata::<FlexParentData>() {
|
if let Some(metadata) = child.metadata::<FlexParentData>() {
|
||||||
if metadata.float {
|
if metadata.float {
|
||||||
|
@ -372,11 +360,9 @@ impl<V: 'static> Element<V> for Flex<V> {
|
||||||
|
|
||||||
child.paint(scene, aligned_child_origin, visible_bounds, view, cx);
|
child.paint(scene, aligned_child_origin, visible_bounds, view, cx);
|
||||||
|
|
||||||
let spacing = if ix == last { 0. } else { self.spacing };
|
|
||||||
|
|
||||||
match self.axis {
|
match self.axis {
|
||||||
Axis::Horizontal => child_origin += vec2f(child.size().x() + spacing, 0.0),
|
Axis::Horizontal => child_origin += vec2f(child.size().x() + self.spacing, 0.0),
|
||||||
Axis::Vertical => child_origin += vec2f(0.0, child.size().y() + spacing),
|
Axis::Vertical => child_origin += vec2f(0.0, child.size().y() + self.spacing),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -152,9 +152,10 @@ impl ToolbarItemView for QuickActionBar {
|
||||||
cx.notify();
|
cx.notify();
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
|
ToolbarItemLocation::PrimaryRight { flex: None }
|
||||||
|
} else {
|
||||||
|
ToolbarItemLocation::Hidden
|
||||||
}
|
}
|
||||||
|
|
||||||
ToolbarItemLocation::PrimaryRight { flex: None }
|
|
||||||
}
|
}
|
||||||
None => {
|
None => {
|
||||||
self.active_item = None;
|
self.active_item = None;
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
history::SearchHistory,
|
history::SearchHistory,
|
||||||
mode::{next_mode, SearchMode},
|
mode::{next_mode, SearchMode, Side},
|
||||||
search_bar::{render_nav_button, render_search_mode_button},
|
search_bar::{render_nav_button, render_search_mode_button},
|
||||||
CycleMode, NextHistoryQuery, PreviousHistoryQuery, SearchOptions, SelectAllMatches,
|
CycleMode, NextHistoryQuery, PreviousHistoryQuery, SearchOptions, SelectAllMatches,
|
||||||
SelectNextMatch, SelectPrevMatch, ToggleCaseSensitive, ToggleWholeWord,
|
SelectNextMatch, SelectPrevMatch, ToggleCaseSensitive, ToggleWholeWord,
|
||||||
|
@ -156,11 +156,12 @@ impl View for BufferSearchBar {
|
||||||
self.query_editor.update(cx, |editor, cx| {
|
self.query_editor.update(cx, |editor, cx| {
|
||||||
editor.set_placeholder_text(new_placeholder_text, cx);
|
editor.set_placeholder_text(new_placeholder_text, cx);
|
||||||
});
|
});
|
||||||
let search_button_for_mode = |mode, cx: &mut ViewContext<BufferSearchBar>| {
|
let search_button_for_mode = |mode, side, cx: &mut ViewContext<BufferSearchBar>| {
|
||||||
let is_active = self.current_mode == mode;
|
let is_active = self.current_mode == mode;
|
||||||
|
|
||||||
render_search_mode_button(
|
render_search_mode_button(
|
||||||
mode,
|
mode,
|
||||||
|
side,
|
||||||
is_active,
|
is_active,
|
||||||
move |_, this, cx| {
|
move |_, this, cx| {
|
||||||
this.activate_search_mode(mode, cx);
|
this.activate_search_mode(mode, cx);
|
||||||
|
@ -212,20 +213,11 @@ impl View for BufferSearchBar {
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
|
|
||||||
let icon_style = theme.search.editor_icon.clone();
|
let query_column = Flex::row()
|
||||||
let nav_column = Flex::row()
|
|
||||||
.with_child(self.render_action_button("Select All", cx))
|
|
||||||
.with_child(nav_button_for_direction("<", Direction::Prev, cx))
|
|
||||||
.with_child(nav_button_for_direction(">", Direction::Next, cx))
|
|
||||||
.with_child(Flex::row().with_children(match_count))
|
|
||||||
.constrained()
|
|
||||||
.with_height(theme.search.search_bar_row_height);
|
|
||||||
|
|
||||||
let query = Flex::row()
|
|
||||||
.with_child(
|
.with_child(
|
||||||
Svg::for_style(icon_style.icon)
|
Svg::for_style(theme.search.editor_icon.clone().icon)
|
||||||
.contained()
|
.contained()
|
||||||
.with_style(icon_style.container),
|
.with_style(theme.search.editor_icon.clone().container),
|
||||||
)
|
)
|
||||||
.with_child(ChildView::new(&self.query_editor, cx).flex(1., true))
|
.with_child(ChildView::new(&self.query_editor, cx).flex(1., true))
|
||||||
.with_child(
|
.with_child(
|
||||||
|
@ -244,49 +236,45 @@ impl View for BufferSearchBar {
|
||||||
.contained(),
|
.contained(),
|
||||||
)
|
)
|
||||||
.align_children_center()
|
.align_children_center()
|
||||||
.flex(1., true);
|
|
||||||
let editor_column = Flex::row()
|
|
||||||
.with_child(
|
|
||||||
query
|
|
||||||
.contained()
|
|
||||||
.with_style(query_container_style)
|
|
||||||
.constrained()
|
|
||||||
.with_min_width(theme.search.editor.min_width)
|
|
||||||
.with_max_width(theme.search.editor.max_width)
|
|
||||||
.with_height(theme.search.search_bar_row_height)
|
|
||||||
.flex(1., false),
|
|
||||||
)
|
|
||||||
.contained()
|
.contained()
|
||||||
|
.with_style(query_container_style)
|
||||||
.constrained()
|
.constrained()
|
||||||
|
.with_min_width(theme.search.editor.min_width)
|
||||||
|
.with_max_width(theme.search.editor.max_width)
|
||||||
.with_height(theme.search.search_bar_row_height)
|
.with_height(theme.search.search_bar_row_height)
|
||||||
.flex(1., false);
|
.flex(1., false);
|
||||||
|
|
||||||
let mode_column = Flex::row()
|
let mode_column = Flex::row()
|
||||||
.with_child(
|
.with_child(search_button_for_mode(
|
||||||
Flex::row()
|
SearchMode::Text,
|
||||||
.with_child(search_button_for_mode(SearchMode::Text, cx))
|
Some(Side::Left),
|
||||||
.with_child(search_button_for_mode(SearchMode::Regex, cx))
|
|
||||||
.contained()
|
|
||||||
.with_style(theme.search.modes_container),
|
|
||||||
)
|
|
||||||
.with_child(super::search_bar::render_close_button(
|
|
||||||
"Dismiss Buffer Search",
|
|
||||||
&theme.search,
|
|
||||||
cx,
|
cx,
|
||||||
|_, this, cx| this.dismiss(&Default::default(), cx),
|
|
||||||
Some(Box::new(Dismiss)),
|
|
||||||
))
|
))
|
||||||
|
.with_child(search_button_for_mode(
|
||||||
|
SearchMode::Regex,
|
||||||
|
Some(Side::Right),
|
||||||
|
cx,
|
||||||
|
))
|
||||||
|
.contained()
|
||||||
|
.with_style(theme.search.modes_container)
|
||||||
|
.constrained()
|
||||||
|
.with_height(theme.search.search_bar_row_height);
|
||||||
|
|
||||||
|
let nav_column = Flex::row()
|
||||||
|
.with_child(self.render_action_button("all", cx))
|
||||||
|
.with_child(Flex::row().with_children(match_count))
|
||||||
|
.with_child(nav_button_for_direction("<", Direction::Prev, cx))
|
||||||
|
.with_child(nav_button_for_direction(">", Direction::Next, cx))
|
||||||
.constrained()
|
.constrained()
|
||||||
.with_height(theme.search.search_bar_row_height)
|
.with_height(theme.search.search_bar_row_height)
|
||||||
.aligned()
|
|
||||||
.right()
|
|
||||||
.flex_float();
|
.flex_float();
|
||||||
|
|
||||||
Flex::row()
|
Flex::row()
|
||||||
.with_child(editor_column)
|
.with_child(query_column)
|
||||||
.with_child(nav_column)
|
|
||||||
.with_child(mode_column)
|
.with_child(mode_column)
|
||||||
|
.with_child(nav_column)
|
||||||
.contained()
|
.contained()
|
||||||
.with_style(theme.search.container)
|
.with_style(theme.search.container)
|
||||||
.aligned()
|
|
||||||
.into_any_named("search bar")
|
.into_any_named("search bar")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -340,8 +328,9 @@ impl ToolbarItemView for BufferSearchBar {
|
||||||
ToolbarItemLocation::Hidden
|
ToolbarItemLocation::Hidden
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn row_count(&self, _: &ViewContext<Self>) -> usize {
|
fn row_count(&self, _: &ViewContext<Self>) -> usize {
|
||||||
2
|
1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -48,41 +48,18 @@ impl SearchMode {
|
||||||
SearchMode::Regex => Box::new(ActivateRegexMode),
|
SearchMode::Regex => Box::new(ActivateRegexMode),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn border_right(&self) -> bool {
|
|
||||||
match self {
|
|
||||||
SearchMode::Regex => true,
|
|
||||||
SearchMode::Text => true,
|
|
||||||
SearchMode::Semantic => true,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) fn border_left(&self) -> bool {
|
|
||||||
match self {
|
|
||||||
SearchMode::Text => true,
|
|
||||||
_ => false,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) fn button_side(&self) -> Option<Side> {
|
|
||||||
match self {
|
|
||||||
SearchMode::Text => Some(Side::Left),
|
|
||||||
SearchMode::Semantic => None,
|
|
||||||
SearchMode::Regex => Some(Side::Right),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn next_mode(mode: &SearchMode, semantic_enabled: bool) -> SearchMode {
|
pub(crate) fn next_mode(mode: &SearchMode, semantic_enabled: bool) -> SearchMode {
|
||||||
let next_text_state = if semantic_enabled {
|
|
||||||
SearchMode::Semantic
|
|
||||||
} else {
|
|
||||||
SearchMode::Regex
|
|
||||||
};
|
|
||||||
|
|
||||||
match mode {
|
match mode {
|
||||||
SearchMode::Text => next_text_state,
|
SearchMode::Text => SearchMode::Regex,
|
||||||
SearchMode::Semantic => SearchMode::Regex,
|
SearchMode::Regex => {
|
||||||
SearchMode::Regex => SearchMode::Text,
|
if semantic_enabled {
|
||||||
|
SearchMode::Semantic
|
||||||
|
} else {
|
||||||
|
SearchMode::Text
|
||||||
|
}
|
||||||
|
}
|
||||||
|
SearchMode::Semantic => SearchMode::Text,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
history::SearchHistory,
|
history::SearchHistory,
|
||||||
mode::SearchMode,
|
mode::{SearchMode, Side},
|
||||||
search_bar::{render_nav_button, render_option_button_icon, render_search_mode_button},
|
search_bar::{render_nav_button, render_option_button_icon, render_search_mode_button},
|
||||||
ActivateRegexMode, CycleMode, NextHistoryQuery, PreviousHistoryQuery, SearchOptions,
|
ActivateRegexMode, CycleMode, NextHistoryQuery, PreviousHistoryQuery, SearchOptions,
|
||||||
SelectNextMatch, SelectPrevMatch, ToggleCaseSensitive, ToggleWholeWord,
|
SelectNextMatch, SelectPrevMatch, ToggleCaseSensitive, ToggleWholeWord,
|
||||||
|
@ -1424,8 +1424,13 @@ impl View for ProjectSearchBar {
|
||||||
},
|
},
|
||||||
cx,
|
cx,
|
||||||
);
|
);
|
||||||
|
|
||||||
let search = _search.read(cx);
|
let search = _search.read(cx);
|
||||||
|
let is_semantic_available = SemanticIndex::enabled(cx);
|
||||||
let is_semantic_disabled = search.semantic_state.is_none();
|
let is_semantic_disabled = search.semantic_state.is_none();
|
||||||
|
let icon_style = theme.search.editor_icon.clone();
|
||||||
|
let is_active = search.active_match_index.is_some();
|
||||||
|
|
||||||
let render_option_button_icon = |path, option, cx: &mut ViewContext<Self>| {
|
let render_option_button_icon = |path, option, cx: &mut ViewContext<Self>| {
|
||||||
crate::search_bar::render_option_button_icon(
|
crate::search_bar::render_option_button_icon(
|
||||||
self.is_option_enabled(option, cx),
|
self.is_option_enabled(option, cx),
|
||||||
|
@ -1451,28 +1456,23 @@ impl View for ProjectSearchBar {
|
||||||
render_option_button_icon("icons/word_search_12.svg", SearchOptions::WHOLE_WORD, cx)
|
render_option_button_icon("icons/word_search_12.svg", SearchOptions::WHOLE_WORD, cx)
|
||||||
});
|
});
|
||||||
|
|
||||||
let search = _search.read(cx);
|
let search_button_for_mode = |mode, side, cx: &mut ViewContext<ProjectSearchBar>| {
|
||||||
let icon_style = theme.search.editor_icon.clone();
|
let is_active = if let Some(search) = self.active_project_search.as_ref() {
|
||||||
|
let search = search.read(cx);
|
||||||
// Editor Functionality
|
search.current_mode == mode
|
||||||
let query = Flex::row()
|
} else {
|
||||||
.with_child(
|
false
|
||||||
Svg::for_style(icon_style.icon)
|
};
|
||||||
.contained()
|
render_search_mode_button(
|
||||||
.with_style(icon_style.container),
|
mode,
|
||||||
|
side,
|
||||||
|
is_active,
|
||||||
|
move |_, this, cx| {
|
||||||
|
this.activate_search_mode(mode, cx);
|
||||||
|
},
|
||||||
|
cx,
|
||||||
)
|
)
|
||||||
.with_child(ChildView::new(&search.query_editor, cx).flex(1., true))
|
};
|
||||||
.with_child(
|
|
||||||
Flex::row()
|
|
||||||
.with_child(filter_button)
|
|
||||||
.with_children(case_sensitive)
|
|
||||||
.with_children(whole_word)
|
|
||||||
.flex(1., false)
|
|
||||||
.constrained()
|
|
||||||
.contained(),
|
|
||||||
)
|
|
||||||
.align_children_center()
|
|
||||||
.flex(1., true);
|
|
||||||
|
|
||||||
let search = _search.read(cx);
|
let search = _search.read(cx);
|
||||||
|
|
||||||
|
@ -1490,50 +1490,6 @@ impl View for ProjectSearchBar {
|
||||||
theme.search.include_exclude_editor.input.container
|
theme.search.include_exclude_editor.input.container
|
||||||
};
|
};
|
||||||
|
|
||||||
let included_files_view = ChildView::new(&search.included_files_editor, cx)
|
|
||||||
.contained()
|
|
||||||
.flex(1., true);
|
|
||||||
let excluded_files_view = ChildView::new(&search.excluded_files_editor, cx)
|
|
||||||
.contained()
|
|
||||||
.flex(1., true);
|
|
||||||
let filters = search.filters_enabled.then(|| {
|
|
||||||
Flex::row()
|
|
||||||
.with_child(
|
|
||||||
included_files_view
|
|
||||||
.contained()
|
|
||||||
.with_style(include_container_style)
|
|
||||||
.constrained()
|
|
||||||
.with_height(theme.search.search_bar_row_height)
|
|
||||||
.with_min_width(theme.search.include_exclude_editor.min_width)
|
|
||||||
.with_max_width(theme.search.include_exclude_editor.max_width),
|
|
||||||
)
|
|
||||||
.with_child(
|
|
||||||
excluded_files_view
|
|
||||||
.contained()
|
|
||||||
.with_style(exclude_container_style)
|
|
||||||
.constrained()
|
|
||||||
.with_height(theme.search.search_bar_row_height)
|
|
||||||
.with_min_width(theme.search.include_exclude_editor.min_width)
|
|
||||||
.with_max_width(theme.search.include_exclude_editor.max_width),
|
|
||||||
)
|
|
||||||
.contained()
|
|
||||||
.with_padding_top(theme.workspace.toolbar.container.padding.bottom)
|
|
||||||
});
|
|
||||||
|
|
||||||
let editor_column = Flex::column()
|
|
||||||
.with_child(
|
|
||||||
query
|
|
||||||
.contained()
|
|
||||||
.with_style(query_container_style)
|
|
||||||
.constrained()
|
|
||||||
.with_min_width(theme.search.editor.min_width)
|
|
||||||
.with_max_width(theme.search.editor.max_width)
|
|
||||||
.with_height(theme.search.search_bar_row_height)
|
|
||||||
.flex(1., false),
|
|
||||||
)
|
|
||||||
.with_children(filters)
|
|
||||||
.flex(1., false);
|
|
||||||
|
|
||||||
let matches = search.active_match_index.map(|match_ix| {
|
let matches = search.active_match_index.map(|match_ix| {
|
||||||
Label::new(
|
Label::new(
|
||||||
format!(
|
format!(
|
||||||
|
@ -1548,25 +1504,81 @@ impl View for ProjectSearchBar {
|
||||||
.aligned()
|
.aligned()
|
||||||
});
|
});
|
||||||
|
|
||||||
let search_button_for_mode = |mode, cx: &mut ViewContext<ProjectSearchBar>| {
|
let query_column = Flex::column()
|
||||||
let is_active = if let Some(search) = self.active_project_search.as_ref() {
|
.with_spacing(theme.search.search_row_spacing)
|
||||||
let search = search.read(cx);
|
.with_child(
|
||||||
search.current_mode == mode
|
Flex::row()
|
||||||
} else {
|
.with_child(
|
||||||
false
|
Svg::for_style(icon_style.icon)
|
||||||
};
|
.contained()
|
||||||
render_search_mode_button(
|
.with_style(icon_style.container),
|
||||||
mode,
|
)
|
||||||
is_active,
|
.with_child(ChildView::new(&search.query_editor, cx).flex(1., true))
|
||||||
move |_, this, cx| {
|
.with_child(
|
||||||
this.activate_search_mode(mode, cx);
|
Flex::row()
|
||||||
},
|
.with_child(filter_button)
|
||||||
cx,
|
.with_children(case_sensitive)
|
||||||
|
.with_children(whole_word)
|
||||||
|
.flex(1., false)
|
||||||
|
.constrained()
|
||||||
|
.contained(),
|
||||||
|
)
|
||||||
|
.align_children_center()
|
||||||
|
.contained()
|
||||||
|
.with_style(query_container_style)
|
||||||
|
.constrained()
|
||||||
|
.with_min_width(theme.search.editor.min_width)
|
||||||
|
.with_max_width(theme.search.editor.max_width)
|
||||||
|
.with_height(theme.search.search_bar_row_height)
|
||||||
|
.flex(1., false),
|
||||||
)
|
)
|
||||||
};
|
.with_children(search.filters_enabled.then(|| {
|
||||||
let is_active = search.active_match_index.is_some();
|
Flex::row()
|
||||||
let semantic_index = SemanticIndex::enabled(cx)
|
.with_child(
|
||||||
.then(|| search_button_for_mode(SearchMode::Semantic, cx));
|
ChildView::new(&search.included_files_editor, cx)
|
||||||
|
.contained()
|
||||||
|
.with_style(include_container_style)
|
||||||
|
.constrained()
|
||||||
|
.with_height(theme.search.search_bar_row_height)
|
||||||
|
.flex(1., true),
|
||||||
|
)
|
||||||
|
.with_child(
|
||||||
|
ChildView::new(&search.excluded_files_editor, cx)
|
||||||
|
.contained()
|
||||||
|
.with_style(exclude_container_style)
|
||||||
|
.constrained()
|
||||||
|
.with_height(theme.search.search_bar_row_height)
|
||||||
|
.flex(1., true),
|
||||||
|
)
|
||||||
|
.constrained()
|
||||||
|
.with_min_width(theme.search.editor.min_width)
|
||||||
|
.with_max_width(theme.search.editor.max_width)
|
||||||
|
.flex(1., false)
|
||||||
|
}))
|
||||||
|
.flex(1., false);
|
||||||
|
|
||||||
|
let mode_column =
|
||||||
|
Flex::row()
|
||||||
|
.with_child(search_button_for_mode(
|
||||||
|
SearchMode::Text,
|
||||||
|
Some(Side::Left),
|
||||||
|
cx,
|
||||||
|
))
|
||||||
|
.with_child(search_button_for_mode(
|
||||||
|
SearchMode::Regex,
|
||||||
|
if is_semantic_available {
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
Some(Side::Right)
|
||||||
|
},
|
||||||
|
cx,
|
||||||
|
))
|
||||||
|
.with_children(is_semantic_available.then(|| {
|
||||||
|
search_button_for_mode(SearchMode::Semantic, Some(Side::Right), cx)
|
||||||
|
}))
|
||||||
|
.contained()
|
||||||
|
.with_style(theme.search.modes_container);
|
||||||
|
|
||||||
let nav_button_for_direction = |label, direction, cx: &mut ViewContext<Self>| {
|
let nav_button_for_direction = |label, direction, cx: &mut ViewContext<Self>| {
|
||||||
render_nav_button(
|
render_nav_button(
|
||||||
label,
|
label,
|
||||||
|
@ -1582,43 +1594,17 @@ impl View for ProjectSearchBar {
|
||||||
};
|
};
|
||||||
|
|
||||||
let nav_column = Flex::row()
|
let nav_column = Flex::row()
|
||||||
|
.with_child(Flex::row().with_children(matches))
|
||||||
.with_child(nav_button_for_direction("<", Direction::Prev, cx))
|
.with_child(nav_button_for_direction("<", Direction::Prev, cx))
|
||||||
.with_child(nav_button_for_direction(">", Direction::Next, cx))
|
.with_child(nav_button_for_direction(">", Direction::Next, cx))
|
||||||
.with_child(Flex::row().with_children(matches))
|
|
||||||
.constrained()
|
|
||||||
.with_height(theme.search.search_bar_row_height);
|
|
||||||
|
|
||||||
let mode_column = Flex::row()
|
|
||||||
.with_child(
|
|
||||||
Flex::row()
|
|
||||||
.with_child(search_button_for_mode(SearchMode::Text, cx))
|
|
||||||
.with_children(semantic_index)
|
|
||||||
.with_child(search_button_for_mode(SearchMode::Regex, cx))
|
|
||||||
.contained()
|
|
||||||
.with_style(theme.search.modes_container),
|
|
||||||
)
|
|
||||||
.with_child(super::search_bar::render_close_button(
|
|
||||||
"Dismiss Project Search",
|
|
||||||
&theme.search,
|
|
||||||
cx,
|
|
||||||
|_, this, cx| {
|
|
||||||
if let Some(search) = this.active_project_search.as_mut() {
|
|
||||||
search.update(cx, |_, cx| cx.emit(ViewEvent::Dismiss))
|
|
||||||
}
|
|
||||||
},
|
|
||||||
None,
|
|
||||||
))
|
|
||||||
.constrained()
|
.constrained()
|
||||||
.with_height(theme.search.search_bar_row_height)
|
.with_height(theme.search.search_bar_row_height)
|
||||||
.aligned()
|
|
||||||
.right()
|
|
||||||
.top()
|
|
||||||
.flex_float();
|
.flex_float();
|
||||||
|
|
||||||
Flex::row()
|
Flex::row()
|
||||||
.with_child(editor_column)
|
.with_child(query_column)
|
||||||
.with_child(nav_column)
|
|
||||||
.with_child(mode_column)
|
.with_child(mode_column)
|
||||||
|
.with_child(nav_column)
|
||||||
.contained()
|
.contained()
|
||||||
.with_style(theme.search.container)
|
.with_style(theme.search.container)
|
||||||
.into_any_named("project search")
|
.into_any_named("project search")
|
||||||
|
@ -1647,7 +1633,7 @@ impl ToolbarItemView for ProjectSearchBar {
|
||||||
self.subscription = Some(cx.observe(&search, |_, _, cx| cx.notify()));
|
self.subscription = Some(cx.observe(&search, |_, _, cx| cx.notify()));
|
||||||
self.active_project_search = Some(search);
|
self.active_project_search = Some(search);
|
||||||
ToolbarItemLocation::PrimaryLeft {
|
ToolbarItemLocation::PrimaryLeft {
|
||||||
flex: Some((1., false)),
|
flex: Some((1., true)),
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
ToolbarItemLocation::Hidden
|
ToolbarItemLocation::Hidden
|
||||||
|
@ -1655,13 +1641,12 @@ impl ToolbarItemView for ProjectSearchBar {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn row_count(&self, cx: &ViewContext<Self>) -> usize {
|
fn row_count(&self, cx: &ViewContext<Self>) -> usize {
|
||||||
self.active_project_search
|
if let Some(search) = self.active_project_search.as_ref() {
|
||||||
.as_ref()
|
if search.read(cx).filters_enabled {
|
||||||
.map(|search| {
|
return 2;
|
||||||
let offset = search.read(cx).filters_enabled as usize;
|
}
|
||||||
2 + offset
|
}
|
||||||
})
|
1
|
||||||
.unwrap_or_else(|| 2)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -13,34 +13,6 @@ use crate::{
|
||||||
SelectNextMatch, SelectPrevMatch,
|
SelectNextMatch, SelectPrevMatch,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub(super) fn render_close_button<V: View>(
|
|
||||||
tooltip: &'static str,
|
|
||||||
theme: &theme::Search,
|
|
||||||
cx: &mut ViewContext<V>,
|
|
||||||
on_click: impl Fn(MouseClick, &mut V, &mut EventContext<V>) + 'static,
|
|
||||||
dismiss_action: Option<Box<dyn Action>>,
|
|
||||||
) -> AnyElement<V> {
|
|
||||||
let tooltip_style = theme::current(cx).tooltip.clone();
|
|
||||||
|
|
||||||
enum CloseButton {}
|
|
||||||
MouseEventHandler::new::<CloseButton, _>(0, cx, |state, _| {
|
|
||||||
let style = theme.dismiss_button.style_for(state);
|
|
||||||
Svg::new("icons/x_mark_8.svg")
|
|
||||||
.with_color(style.color)
|
|
||||||
.constrained()
|
|
||||||
.with_width(style.icon_width)
|
|
||||||
.aligned()
|
|
||||||
.contained()
|
|
||||||
.with_style(style.container)
|
|
||||||
.constrained()
|
|
||||||
.with_height(theme.search_bar_row_height)
|
|
||||||
})
|
|
||||||
.on_click(MouseButton::Left, on_click)
|
|
||||||
.with_cursor_style(CursorStyle::PointingHand)
|
|
||||||
.with_tooltip::<CloseButton>(0, tooltip.to_string(), dismiss_action, tooltip_style, cx)
|
|
||||||
.into_any()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(super) fn render_nav_button<V: View>(
|
pub(super) fn render_nav_button<V: View>(
|
||||||
icon: &'static str,
|
icon: &'static str,
|
||||||
direction: Direction,
|
direction: Direction,
|
||||||
|
@ -111,6 +83,7 @@ pub(super) fn render_nav_button<V: View>(
|
||||||
|
|
||||||
pub(crate) fn render_search_mode_button<V: View>(
|
pub(crate) fn render_search_mode_button<V: View>(
|
||||||
mode: SearchMode,
|
mode: SearchMode,
|
||||||
|
side: Option<Side>,
|
||||||
is_active: bool,
|
is_active: bool,
|
||||||
on_click: impl Fn(MouseClick, &mut V, &mut EventContext<V>) + 'static,
|
on_click: impl Fn(MouseClick, &mut V, &mut EventContext<V>) + 'static,
|
||||||
cx: &mut ViewContext<V>,
|
cx: &mut ViewContext<V>,
|
||||||
|
@ -119,41 +92,41 @@ pub(crate) fn render_search_mode_button<V: View>(
|
||||||
enum SearchModeButton {}
|
enum SearchModeButton {}
|
||||||
MouseEventHandler::new::<SearchModeButton, _>(mode.region_id(), cx, |state, cx| {
|
MouseEventHandler::new::<SearchModeButton, _>(mode.region_id(), cx, |state, cx| {
|
||||||
let theme = theme::current(cx);
|
let theme = theme::current(cx);
|
||||||
let mut style = theme
|
let style = theme
|
||||||
.search
|
.search
|
||||||
.mode_button
|
.mode_button
|
||||||
.in_state(is_active)
|
.in_state(is_active)
|
||||||
.style_for(state)
|
.style_for(state)
|
||||||
.clone();
|
.clone();
|
||||||
style.container.border.left = mode.border_left();
|
|
||||||
style.container.border.right = mode.border_right();
|
|
||||||
|
|
||||||
let label = Label::new(mode.label(), style.text.clone())
|
let mut container_style = style.container;
|
||||||
.aligned()
|
if let Some(button_side) = side {
|
||||||
.contained();
|
|
||||||
let mut container_style = style.container.clone();
|
|
||||||
if let Some(button_side) = mode.button_side() {
|
|
||||||
if button_side == Side::Left {
|
if button_side == Side::Left {
|
||||||
|
container_style.border.left = true;
|
||||||
container_style.corner_radii = CornerRadii {
|
container_style.corner_radii = CornerRadii {
|
||||||
bottom_right: 0.,
|
bottom_right: 0.,
|
||||||
top_right: 0.,
|
top_right: 0.,
|
||||||
..container_style.corner_radii
|
..container_style.corner_radii
|
||||||
};
|
};
|
||||||
label.with_style(container_style)
|
|
||||||
} else {
|
} else {
|
||||||
|
container_style.border.left = false;
|
||||||
container_style.corner_radii = CornerRadii {
|
container_style.corner_radii = CornerRadii {
|
||||||
bottom_left: 0.,
|
bottom_left: 0.,
|
||||||
top_left: 0.,
|
top_left: 0.,
|
||||||
..container_style.corner_radii
|
..container_style.corner_radii
|
||||||
};
|
};
|
||||||
label.with_style(container_style)
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
container_style.border.left = false;
|
||||||
container_style.corner_radii = CornerRadii::default();
|
container_style.corner_radii = CornerRadii::default();
|
||||||
label.with_style(container_style)
|
|
||||||
}
|
}
|
||||||
.constrained()
|
|
||||||
.with_height(theme.search.search_bar_row_height)
|
Label::new(mode.label(), style.text)
|
||||||
|
.aligned()
|
||||||
|
.contained()
|
||||||
|
.with_style(container_style)
|
||||||
|
.constrained()
|
||||||
|
.with_height(theme.search.search_bar_row_height)
|
||||||
})
|
})
|
||||||
.on_click(MouseButton::Left, on_click)
|
.on_click(MouseButton::Left, on_click)
|
||||||
.with_cursor_style(CursorStyle::PointingHand)
|
.with_cursor_style(CursorStyle::PointingHand)
|
||||||
|
|
|
@ -437,11 +437,11 @@ pub struct Search {
|
||||||
pub match_index: ContainedText,
|
pub match_index: ContainedText,
|
||||||
pub major_results_status: TextStyle,
|
pub major_results_status: TextStyle,
|
||||||
pub minor_results_status: TextStyle,
|
pub minor_results_status: TextStyle,
|
||||||
pub dismiss_button: Interactive<IconButton>,
|
|
||||||
pub editor_icon: IconStyle,
|
pub editor_icon: IconStyle,
|
||||||
pub mode_button: Toggleable<Interactive<ContainedText>>,
|
pub mode_button: Toggleable<Interactive<ContainedText>>,
|
||||||
pub nav_button: Toggleable<Interactive<ContainedLabel>>,
|
pub nav_button: Toggleable<Interactive<ContainedLabel>>,
|
||||||
pub search_bar_row_height: f32,
|
pub search_bar_row_height: f32,
|
||||||
|
pub search_row_spacing: f32,
|
||||||
pub option_button_height: f32,
|
pub option_button_height: f32,
|
||||||
pub modes_container: ContainerStyle,
|
pub modes_container: ContainerStyle,
|
||||||
}
|
}
|
||||||
|
|
|
@ -81,10 +81,7 @@ impl View for Toolbar {
|
||||||
|
|
||||||
ToolbarItemLocation::PrimaryLeft { flex } => {
|
ToolbarItemLocation::PrimaryLeft { flex } => {
|
||||||
primary_items_row_count = primary_items_row_count.max(item.row_count(cx));
|
primary_items_row_count = primary_items_row_count.max(item.row_count(cx));
|
||||||
let left_item = ChildView::new(item.as_any(), cx)
|
let left_item = ChildView::new(item.as_any(), cx).aligned();
|
||||||
.aligned()
|
|
||||||
.contained()
|
|
||||||
.with_margin_right(spacing);
|
|
||||||
if let Some((flex, expanded)) = flex {
|
if let Some((flex, expanded)) = flex {
|
||||||
primary_left_items.push(left_item.flex(flex, expanded).into_any());
|
primary_left_items.push(left_item.flex(flex, expanded).into_any());
|
||||||
} else {
|
} else {
|
||||||
|
@ -94,11 +91,7 @@ impl View for Toolbar {
|
||||||
|
|
||||||
ToolbarItemLocation::PrimaryRight { flex } => {
|
ToolbarItemLocation::PrimaryRight { flex } => {
|
||||||
primary_items_row_count = primary_items_row_count.max(item.row_count(cx));
|
primary_items_row_count = primary_items_row_count.max(item.row_count(cx));
|
||||||
let right_item = ChildView::new(item.as_any(), cx)
|
let right_item = ChildView::new(item.as_any(), cx).aligned().flex_float();
|
||||||
.aligned()
|
|
||||||
.contained()
|
|
||||||
.with_margin_left(spacing)
|
|
||||||
.flex_float();
|
|
||||||
if let Some((flex, expanded)) = flex {
|
if let Some((flex, expanded)) = flex {
|
||||||
primary_right_items.push(right_item.flex(flex, expanded).into_any());
|
primary_right_items.push(right_item.flex(flex, expanded).into_any());
|
||||||
} else {
|
} else {
|
||||||
|
@ -120,7 +113,7 @@ impl View for Toolbar {
|
||||||
let container_style = theme.container;
|
let container_style = theme.container;
|
||||||
let height = theme.height * primary_items_row_count as f32;
|
let height = theme.height * primary_items_row_count as f32;
|
||||||
|
|
||||||
let mut primary_items = Flex::row();
|
let mut primary_items = Flex::row().with_spacing(spacing);
|
||||||
primary_items.extend(primary_left_items);
|
primary_items.extend(primary_left_items);
|
||||||
primary_items.extend(primary_right_items);
|
primary_items.extend(primary_right_items);
|
||||||
|
|
||||||
|
|
|
@ -1,78 +0,0 @@
|
||||||
import { Interactive, interactive, toggleable, Toggleable } from "../element"
|
|
||||||
import { TextStyle, background, text } from "../style_tree/components"
|
|
||||||
import { useTheme } from "../theme"
|
|
||||||
import { Button } from "./button"
|
|
||||||
|
|
||||||
type LabelButtonStyle = {
|
|
||||||
corder_radius: number
|
|
||||||
background: string | null
|
|
||||||
padding: {
|
|
||||||
top: number
|
|
||||||
bottom: number
|
|
||||||
left: number
|
|
||||||
right: number
|
|
||||||
},
|
|
||||||
margin: Button.Options['margin']
|
|
||||||
button_height: number
|
|
||||||
} & TextStyle
|
|
||||||
|
|
||||||
/** Styles an Interactive<ContainedText> */
|
|
||||||
export function label_button_style(
|
|
||||||
options: Partial<Button.Options> = {
|
|
||||||
variant: Button.variant.Default,
|
|
||||||
shape: Button.shape.Rectangle,
|
|
||||||
states: {
|
|
||||||
hovered: true,
|
|
||||||
pressed: true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
): Interactive<LabelButtonStyle> {
|
|
||||||
const theme = useTheme()
|
|
||||||
|
|
||||||
const base = Button.button_base(options)
|
|
||||||
const layer = options.layer ?? theme.middle
|
|
||||||
const color = options.color ?? "base"
|
|
||||||
|
|
||||||
const default_state = {
|
|
||||||
...base,
|
|
||||||
...text(layer ?? theme.lowest, "sans", color),
|
|
||||||
font_size: Button.FONT_SIZE,
|
|
||||||
}
|
|
||||||
|
|
||||||
return interactive({
|
|
||||||
base: default_state,
|
|
||||||
state: {
|
|
||||||
hovered: {
|
|
||||||
background: background(layer, options.background ?? color, "hovered")
|
|
||||||
},
|
|
||||||
clicked: {
|
|
||||||
background: background(layer, options.background ?? color, "pressed")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Styles an Toggleable<Interactive<ContainedText>> */
|
|
||||||
export function toggle_label_button_style(
|
|
||||||
options: Partial<Button.ToggleableOptions> = {
|
|
||||||
variant: Button.variant.Default,
|
|
||||||
shape: Button.shape.Rectangle,
|
|
||||||
states: {
|
|
||||||
hovered: true,
|
|
||||||
pressed: true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
): Toggleable<Interactive<LabelButtonStyle>> {
|
|
||||||
const activeOptions = {
|
|
||||||
...options,
|
|
||||||
color: options.active_color || options.color,
|
|
||||||
background: options.active_background || options.background
|
|
||||||
}
|
|
||||||
|
|
||||||
return toggleable({
|
|
||||||
state: {
|
|
||||||
inactive: label_button_style(options),
|
|
||||||
active: label_button_style(activeOptions),
|
|
||||||
},
|
|
||||||
})
|
|
||||||
}
|
|
34
styles/src/component/margin.ts
Normal file
34
styles/src/component/margin.ts
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
type MarginOptions = {
|
||||||
|
all?: number
|
||||||
|
left?: number
|
||||||
|
right?: number
|
||||||
|
top?: number
|
||||||
|
bottom?: number
|
||||||
|
}
|
||||||
|
|
||||||
|
export type MarginStyle = {
|
||||||
|
top: number
|
||||||
|
bottom: number
|
||||||
|
left: number
|
||||||
|
right: number
|
||||||
|
}
|
||||||
|
|
||||||
|
export const margin_style = (options: MarginOptions): MarginStyle => {
|
||||||
|
const { all, top, bottom, left, right } = options
|
||||||
|
|
||||||
|
if (all !== undefined) return {
|
||||||
|
top: all,
|
||||||
|
bottom: all,
|
||||||
|
left: all,
|
||||||
|
right: all
|
||||||
|
}
|
||||||
|
|
||||||
|
if (top === undefined && bottom === undefined && left === undefined && right === undefined) throw new Error("Margin must have at least one value")
|
||||||
|
|
||||||
|
return {
|
||||||
|
top: top || 0,
|
||||||
|
bottom: bottom || 0,
|
||||||
|
left: left || 0,
|
||||||
|
right: right || 0
|
||||||
|
}
|
||||||
|
}
|
34
styles/src/component/padding.ts
Normal file
34
styles/src/component/padding.ts
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
type PaddingOptions = {
|
||||||
|
all?: number
|
||||||
|
left?: number
|
||||||
|
right?: number
|
||||||
|
top?: number
|
||||||
|
bottom?: number
|
||||||
|
}
|
||||||
|
|
||||||
|
export type PaddingStyle = {
|
||||||
|
top: number
|
||||||
|
bottom: number
|
||||||
|
left: number
|
||||||
|
right: number
|
||||||
|
}
|
||||||
|
|
||||||
|
export const padding_style = (options: PaddingOptions): PaddingStyle => {
|
||||||
|
const { all, top, bottom, left, right } = options
|
||||||
|
|
||||||
|
if (all !== undefined) return {
|
||||||
|
top: all,
|
||||||
|
bottom: all,
|
||||||
|
left: all,
|
||||||
|
right: all
|
||||||
|
}
|
||||||
|
|
||||||
|
if (top === undefined && bottom === undefined && left === undefined && right === undefined) throw new Error("Padding must have at least one value")
|
||||||
|
|
||||||
|
return {
|
||||||
|
top: top || 0,
|
||||||
|
bottom: bottom || 0,
|
||||||
|
left: left || 0,
|
||||||
|
right: right || 0
|
||||||
|
}
|
||||||
|
}
|
|
@ -17,6 +17,7 @@ interface TextButtonOptions {
|
||||||
variant?: Button.Variant
|
variant?: Button.Variant
|
||||||
color?: keyof Theme["lowest"]
|
color?: keyof Theme["lowest"]
|
||||||
margin?: Partial<Margin>
|
margin?: Partial<Margin>
|
||||||
|
disabled?: boolean
|
||||||
text_properties?: TextProperties
|
text_properties?: TextProperties
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -29,6 +30,7 @@ export function text_button({
|
||||||
color,
|
color,
|
||||||
layer,
|
layer,
|
||||||
margin,
|
margin,
|
||||||
|
disabled,
|
||||||
text_properties,
|
text_properties,
|
||||||
}: TextButtonOptions = {}) {
|
}: TextButtonOptions = {}) {
|
||||||
const theme = useTheme()
|
const theme = useTheme()
|
||||||
|
@ -65,13 +67,17 @@ export function text_button({
|
||||||
state: {
|
state: {
|
||||||
default: {
|
default: {
|
||||||
background: background_color,
|
background: background_color,
|
||||||
color: foreground(layer ?? theme.lowest, color),
|
color:
|
||||||
|
disabled
|
||||||
|
? foreground(layer ?? theme.lowest, "disabled")
|
||||||
|
: foreground(layer ?? theme.lowest, color),
|
||||||
},
|
},
|
||||||
hovered: {
|
hovered:
|
||||||
background: background(layer ?? theme.lowest, color, "hovered"),
|
disabled ? {} : {
|
||||||
color: foreground(layer ?? theme.lowest, color, "hovered"),
|
background: background(layer ?? theme.lowest, color, "hovered"),
|
||||||
},
|
color: foreground(layer ?? theme.lowest, color, "hovered"),
|
||||||
clicked: {
|
},
|
||||||
|
clicked: disabled ? {} : {
|
||||||
background: background(layer ?? theme.lowest, color, "pressed"),
|
background: background(layer ?? theme.lowest, color, "pressed"),
|
||||||
color: foreground(layer ?? theme.lowest, color, "pressed"),
|
color: foreground(layer ?? theme.lowest, color, "pressed"),
|
||||||
},
|
},
|
||||||
|
|
|
@ -2,9 +2,23 @@ import { with_opacity } from "../theme/color"
|
||||||
import { background, border, foreground, text } from "./components"
|
import { background, border, foreground, text } from "./components"
|
||||||
import { interactive, toggleable } from "../element"
|
import { interactive, toggleable } from "../element"
|
||||||
import { useTheme } from "../theme"
|
import { useTheme } from "../theme"
|
||||||
|
import { text_button } from "../component/text_button"
|
||||||
|
|
||||||
|
const search_results = () => {
|
||||||
|
const theme = useTheme()
|
||||||
|
|
||||||
|
return {
|
||||||
|
// TODO: Add an activeMatchBackground on the rust side to differentiate between active and inactive
|
||||||
|
match_background: with_opacity(
|
||||||
|
foreground(theme.highest, "accent"),
|
||||||
|
0.4
|
||||||
|
),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export default function search(): any {
|
export default function search(): any {
|
||||||
const theme = useTheme()
|
const theme = useTheme()
|
||||||
|
const SEARCH_ROW_SPACING = 12
|
||||||
|
|
||||||
// Search input
|
// Search input
|
||||||
const editor = {
|
const editor = {
|
||||||
|
@ -34,12 +48,8 @@ export default function search(): any {
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
padding: { top: 16, bottom: 16, left: 16, right: 16 },
|
padding: { top: 4, bottom: 4 },
|
||||||
// TODO: Add an activeMatchBackground on the rust side to differentiate between active and inactive
|
|
||||||
match_background: with_opacity(
|
|
||||||
foreground(theme.highest, "accent"),
|
|
||||||
0.4
|
|
||||||
),
|
|
||||||
option_button: toggleable({
|
option_button: toggleable({
|
||||||
base: interactive({
|
base: interactive({
|
||||||
base: {
|
base: {
|
||||||
|
@ -153,47 +163,13 @@ export default function search(): any {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
|
// Search tool buttons
|
||||||
|
// HACK: This is not how disabled elements should be created
|
||||||
|
// Disabled elements should use a disabled state of an interactive element, not a toggleable element with the inactive state being disabled
|
||||||
action_button: toggleable({
|
action_button: toggleable({
|
||||||
base: interactive({
|
|
||||||
base: {
|
|
||||||
...text(theme.highest, "mono", "disabled"),
|
|
||||||
background: background(theme.highest, "disabled"),
|
|
||||||
corner_radius: 6,
|
|
||||||
border: border(theme.highest, "disabled"),
|
|
||||||
padding: {
|
|
||||||
// bottom: 2,
|
|
||||||
left: 10,
|
|
||||||
right: 10,
|
|
||||||
// top: 2,
|
|
||||||
},
|
|
||||||
margin: {
|
|
||||||
right: 9,
|
|
||||||
}
|
|
||||||
},
|
|
||||||
state: {
|
|
||||||
hovered: {}
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
state: {
|
state: {
|
||||||
active: interactive({
|
inactive: text_button({ variant: "ghost", layer: theme.highest, disabled: true, margin: { right: SEARCH_ROW_SPACING }, text_properties: { size: "sm" } }),
|
||||||
base: {
|
active: text_button({ variant: "ghost", layer: theme.highest, margin: { right: SEARCH_ROW_SPACING }, text_properties: { size: "sm" } })
|
||||||
...text(theme.highest, "mono", "on"),
|
|
||||||
background: background(theme.highest, "on"),
|
|
||||||
border: border(theme.highest, "on"),
|
|
||||||
},
|
|
||||||
state: {
|
|
||||||
hovered: {
|
|
||||||
...text(theme.highest, "mono", "on", "hovered"),
|
|
||||||
background: background(theme.highest, "on", "hovered"),
|
|
||||||
border: border(theme.highest, "on", "hovered"),
|
|
||||||
},
|
|
||||||
clicked: {
|
|
||||||
...text(theme.highest, "mono", "on", "pressed"),
|
|
||||||
background: background(theme.highest, "on", "pressed"),
|
|
||||||
border: border(theme.highest, "on", "pressed"),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
editor,
|
editor,
|
||||||
|
@ -207,15 +183,15 @@ export default function search(): any {
|
||||||
border: border(theme.highest, "negative"),
|
border: border(theme.highest, "negative"),
|
||||||
},
|
},
|
||||||
match_index: {
|
match_index: {
|
||||||
...text(theme.highest, "mono", "variant"),
|
...text(theme.highest, "mono", { size: "sm" }),
|
||||||
padding: {
|
padding: {
|
||||||
left: 9,
|
right: SEARCH_ROW_SPACING,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
option_button_group: {
|
option_button_group: {
|
||||||
padding: {
|
padding: {
|
||||||
left: 12,
|
left: SEARCH_ROW_SPACING,
|
||||||
right: 12,
|
right: SEARCH_ROW_SPACING,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
include_exclude_inputs: {
|
include_exclude_inputs: {
|
||||||
|
@ -232,52 +208,26 @@ export default function search(): any {
|
||||||
...text(theme.highest, "mono", "variant"),
|
...text(theme.highest, "mono", "variant"),
|
||||||
size: 13,
|
size: 13,
|
||||||
},
|
},
|
||||||
dismiss_button: interactive({
|
// Input Icon
|
||||||
base: {
|
|
||||||
color: foreground(theme.highest, "variant"),
|
|
||||||
icon_width: 14,
|
|
||||||
button_width: 32,
|
|
||||||
corner_radius: 6,
|
|
||||||
padding: {
|
|
||||||
// // top: 10,
|
|
||||||
// bottom: 10,
|
|
||||||
left: 10,
|
|
||||||
right: 10,
|
|
||||||
},
|
|
||||||
|
|
||||||
background: background(theme.highest, "variant"),
|
|
||||||
|
|
||||||
border: border(theme.highest, "on"),
|
|
||||||
},
|
|
||||||
state: {
|
|
||||||
hovered: {
|
|
||||||
color: foreground(theme.highest, "hovered"),
|
|
||||||
background: background(theme.highest, "variant", "hovered")
|
|
||||||
},
|
|
||||||
clicked: {
|
|
||||||
color: foreground(theme.highest, "pressed"),
|
|
||||||
background: background(theme.highest, "variant", "pressed")
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
editor_icon: {
|
editor_icon: {
|
||||||
icon: {
|
icon: {
|
||||||
color: foreground(theme.highest, "variant"),
|
color: foreground(theme.highest, "disabled"),
|
||||||
asset: "icons/magnifying_glass_12.svg",
|
asset: "icons/magnifying_glass.svg",
|
||||||
dimensions: {
|
dimensions: {
|
||||||
width: 12,
|
width: 14,
|
||||||
height: 12,
|
height: 14,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
container: {
|
container: {
|
||||||
margin: { right: 6 },
|
margin: { right: 4 },
|
||||||
padding: { left: 2, right: 2 },
|
padding: { left: 1, right: 1 },
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
// Toggle group buttons - Text | Regex | Semantic
|
||||||
mode_button: toggleable({
|
mode_button: toggleable({
|
||||||
base: interactive({
|
base: interactive({
|
||||||
base: {
|
base: {
|
||||||
...text(theme.highest, "mono", "variant"),
|
...text(theme.highest, "mono", "variant", { size: "sm" }),
|
||||||
background: background(theme.highest, "variant"),
|
background: background(theme.highest, "variant"),
|
||||||
|
|
||||||
border: {
|
border: {
|
||||||
|
@ -285,21 +235,24 @@ export default function search(): any {
|
||||||
left: false,
|
left: false,
|
||||||
right: false
|
right: false
|
||||||
},
|
},
|
||||||
|
margin: {
|
||||||
|
top: 1,
|
||||||
|
bottom: 1,
|
||||||
|
},
|
||||||
padding: {
|
padding: {
|
||||||
left: 10,
|
left: 12,
|
||||||
right: 10,
|
right: 12,
|
||||||
},
|
},
|
||||||
corner_radius: 6,
|
corner_radius: 6,
|
||||||
},
|
},
|
||||||
state: {
|
state: {
|
||||||
hovered: {
|
hovered: {
|
||||||
...text(theme.highest, "mono", "variant", "hovered"),
|
...text(theme.highest, "mono", "variant", "hovered", { size: "sm" }),
|
||||||
background: background(theme.highest, "variant", "hovered"),
|
background: background(theme.highest, "variant", "hovered"),
|
||||||
border: border(theme.highest, "on", "hovered"),
|
border: border(theme.highest, "on", "hovered"),
|
||||||
},
|
},
|
||||||
clicked: {
|
clicked: {
|
||||||
...text(theme.highest, "mono", "variant", "pressed"),
|
...text(theme.highest, "mono", "variant", "pressed", { size: "sm" }),
|
||||||
background: background(theme.highest, "variant", "pressed"),
|
background: background(theme.highest, "variant", "pressed"),
|
||||||
border: border(theme.highest, "on", "pressed"),
|
border: border(theme.highest, "on", "pressed"),
|
||||||
},
|
},
|
||||||
|
@ -308,20 +261,23 @@ export default function search(): any {
|
||||||
state: {
|
state: {
|
||||||
active: {
|
active: {
|
||||||
default: {
|
default: {
|
||||||
...text(theme.highest, "mono", "on"),
|
...text(theme.highest, "mono", "on", { size: "sm" }),
|
||||||
background: background(theme.highest, "on")
|
background: background(theme.highest, "on")
|
||||||
},
|
},
|
||||||
hovered: {
|
hovered: {
|
||||||
...text(theme.highest, "mono", "on", "hovered"),
|
...text(theme.highest, "mono", "on", "hovered", { size: "sm" }),
|
||||||
background: background(theme.highest, "on", "hovered")
|
background: background(theme.highest, "on", "hovered")
|
||||||
},
|
},
|
||||||
clicked: {
|
clicked: {
|
||||||
...text(theme.highest, "mono", "on", "pressed"),
|
...text(theme.highest, "mono", "on", "pressed", { size: "sm" }),
|
||||||
background: background(theme.highest, "on", "pressed")
|
background: background(theme.highest, "on", "pressed")
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
|
// Next/Previous Match buttons
|
||||||
|
// HACK: This is not how disabled elements should be created
|
||||||
|
// Disabled elements should use a disabled state of an interactive element, not a toggleable element with the inactive state being disabled
|
||||||
nav_button: toggleable({
|
nav_button: toggleable({
|
||||||
state: {
|
state: {
|
||||||
inactive: interactive({
|
inactive: interactive({
|
||||||
|
@ -334,7 +290,10 @@ export default function search(): any {
|
||||||
left: false,
|
left: false,
|
||||||
right: false,
|
right: false,
|
||||||
},
|
},
|
||||||
|
margin: {
|
||||||
|
top: 1,
|
||||||
|
bottom: 1,
|
||||||
|
},
|
||||||
padding: {
|
padding: {
|
||||||
left: 10,
|
left: 10,
|
||||||
right: 10,
|
right: 10,
|
||||||
|
@ -354,7 +313,10 @@ export default function search(): any {
|
||||||
left: false,
|
left: false,
|
||||||
right: false,
|
right: false,
|
||||||
},
|
},
|
||||||
|
margin: {
|
||||||
|
top: 1,
|
||||||
|
bottom: 1,
|
||||||
|
},
|
||||||
padding: {
|
padding: {
|
||||||
left: 10,
|
left: 10,
|
||||||
right: 10,
|
right: 10,
|
||||||
|
@ -375,13 +337,10 @@ export default function search(): any {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
search_bar_row_height: 32,
|
search_bar_row_height: 34,
|
||||||
|
search_row_spacing: 8,
|
||||||
option_button_height: 22,
|
option_button_height: 22,
|
||||||
modes_container: {
|
modes_container: {},
|
||||||
margin: {
|
...search_results()
|
||||||
right: 9
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -129,7 +129,7 @@ export default function workspace(): any {
|
||||||
status_bar: statusBar(),
|
status_bar: statusBar(),
|
||||||
titlebar: titlebar(),
|
titlebar: titlebar(),
|
||||||
toolbar: {
|
toolbar: {
|
||||||
height: 34,
|
height: 42,
|
||||||
background: background(theme.highest),
|
background: background(theme.highest),
|
||||||
border: border(theme.highest, { bottom: true }),
|
border: border(theme.highest, { bottom: true }),
|
||||||
item_spacing: 8,
|
item_spacing: 8,
|
||||||
|
@ -138,7 +138,7 @@ export default function workspace(): any {
|
||||||
variant: "ghost",
|
variant: "ghost",
|
||||||
active_color: "accent",
|
active_color: "accent",
|
||||||
}),
|
}),
|
||||||
padding: { left: 8, right: 8, top: 4, bottom: 4 },
|
padding: { left: 8, right: 8 },
|
||||||
},
|
},
|
||||||
breadcrumb_height: 24,
|
breadcrumb_height: 24,
|
||||||
breadcrumbs: interactive({
|
breadcrumbs: interactive({
|
||||||
|
|
|
@ -21,8 +21,7 @@
|
||||||
"experimentalDecorators": true,
|
"experimentalDecorators": true,
|
||||||
"strictPropertyInitialization": false,
|
"strictPropertyInitialization": false,
|
||||||
"skipLibCheck": true,
|
"skipLibCheck": true,
|
||||||
"useUnknownInCatchVariables": false,
|
"useUnknownInCatchVariables": false
|
||||||
"baseUrl": "."
|
|
||||||
},
|
},
|
||||||
"exclude": [
|
"exclude": [
|
||||||
"node_modules"
|
"node_modules"
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue