Detailed changes
@@ -88,8 +88,7 @@ impl<V: 'static> Flex<V> {
cx: &mut LayoutContext<V>,
) {
let cross_axis = self.axis.invert();
- let last = self.children.len() - 1;
- for (ix, child) in &mut self.children.iter_mut().enumerate() {
+ for child in self.children.iter_mut() {
if let Some(metadata) = child.metadata::<FlexParentData>() {
if let Some((flex, expanded)) = metadata.flex {
if expanded != layout_expanded {
@@ -101,10 +100,6 @@ impl<V: 'static> Flex<V> {
} else {
let space_per_flex = *remaining_space / *remaining_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_constraint = match self.axis {
@@ -144,13 +139,12 @@ impl<V: 'static> Element<V> for Flex<V> {
cx: &mut LayoutContext<V>,
) -> (Vector2F, Self::LayoutState) {
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 cross_axis = self.axis.invert();
let mut cross_axis_max: f32 = 0.0;
- let last = self.children.len().saturating_sub(1);
- for (ix, child) in &mut self.children.iter_mut().enumerate() {
+ for child in self.children.iter_mut() {
let metadata = child.metadata::<FlexParentData>();
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);
- fixed_space += size.along(self.axis)
- + if ix == 0 || ix == last {
- self.spacing / 2.
- } else {
- self.spacing
- };
+ fixed_space += size.along(self.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 (ix, child) in &mut self.children.iter_mut().enumerate() {
+ for child in self.children.iter_mut() {
if remaining_space > 0. {
if let Some(metadata) = child.metadata::<FlexParentData>() {
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);
- let spacing = if ix == last { 0. } else { self.spacing };
-
match self.axis {
- Axis::Horizontal => child_origin += vec2f(child.size().x() + spacing, 0.0),
- Axis::Vertical => child_origin += vec2f(0.0, child.size().y() + spacing),
+ Axis::Horizontal => child_origin += vec2f(child.size().x() + self.spacing, 0.0),
+ Axis::Vertical => child_origin += vec2f(0.0, child.size().y() + self.spacing),
}
}
@@ -150,9 +150,10 @@ impl ToolbarItemView for QuickActionBar {
cx.notify();
}
}));
+ ToolbarItemLocation::PrimaryRight { flex: None }
+ } else {
+ ToolbarItemLocation::Hidden
}
-
- ToolbarItemLocation::PrimaryRight { flex: None }
}
None => {
self.active_item = None;
@@ -1,6 +1,6 @@
use crate::{
history::SearchHistory,
- mode::{next_mode, SearchMode},
+ mode::{next_mode, SearchMode, Side},
search_bar::{render_nav_button, render_search_mode_button},
CycleMode, NextHistoryQuery, PreviousHistoryQuery, SearchOptions, SelectAllMatches,
SelectNextMatch, SelectPrevMatch, ToggleCaseSensitive, ToggleWholeWord,
@@ -156,11 +156,12 @@ impl View for BufferSearchBar {
self.query_editor.update(cx, |editor, 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;
render_search_mode_button(
mode,
+ side,
is_active,
move |_, this, cx| {
this.activate_search_mode(mode, cx);
@@ -212,20 +213,11 @@ impl View for BufferSearchBar {
)
};
- let icon_style = theme.search.editor_icon.clone();
- 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()
+ let query_column = Flex::row()
.with_child(
- Svg::for_style(icon_style.icon)
+ Svg::for_style(theme.search.editor_icon.clone().icon)
.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(
@@ -244,49 +236,45 @@ impl View for BufferSearchBar {
.contained(),
)
.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()
+ .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);
+
let mode_column = Flex::row()
- .with_child(
- Flex::row()
- .with_child(search_button_for_mode(SearchMode::Text, cx))
- .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,
+ .with_child(search_button_for_mode(
+ SearchMode::Text,
+ Some(Side::Left),
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()
.with_height(theme.search.search_bar_row_height)
- .aligned()
- .right()
.flex_float();
+
Flex::row()
- .with_child(editor_column)
- .with_child(nav_column)
+ .with_child(query_column)
.with_child(mode_column)
+ .with_child(nav_column)
.contained()
.with_style(theme.search.container)
- .aligned()
.into_any_named("search bar")
}
}
@@ -340,8 +328,9 @@ impl ToolbarItemView for BufferSearchBar {
ToolbarItemLocation::Hidden
}
}
+
fn row_count(&self, _: &ViewContext<Self>) -> usize {
- 2
+ 1
}
}
@@ -48,41 +48,18 @@ impl SearchMode {
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 {
- let next_text_state = if semantic_enabled {
- SearchMode::Semantic
- } else {
- SearchMode::Regex
- };
-
match mode {
- SearchMode::Text => next_text_state,
- SearchMode::Semantic => SearchMode::Regex,
- SearchMode::Regex => SearchMode::Text,
+ SearchMode::Text => SearchMode::Regex,
+ SearchMode::Regex => {
+ if semantic_enabled {
+ SearchMode::Semantic
+ } else {
+ SearchMode::Text
+ }
+ }
+ SearchMode::Semantic => SearchMode::Text,
}
}
@@ -1,6 +1,6 @@
use crate::{
history::SearchHistory,
- mode::SearchMode,
+ mode::{SearchMode, Side},
search_bar::{render_nav_button, render_option_button_icon, render_search_mode_button},
ActivateRegexMode, CycleMode, NextHistoryQuery, PreviousHistoryQuery, SearchOptions,
SelectNextMatch, SelectPrevMatch, ToggleCaseSensitive, ToggleWholeWord,
@@ -1420,8 +1420,13 @@ impl View for ProjectSearchBar {
},
cx,
);
+
let search = _search.read(cx);
+ let is_semantic_available = SemanticIndex::enabled(cx);
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>| {
crate::search_bar::render_option_button_icon(
self.is_option_enabled(option, cx),
@@ -1447,28 +1452,23 @@ impl View for ProjectSearchBar {
render_option_button_icon("icons/word_search_12.svg", SearchOptions::WHOLE_WORD, cx)
});
- let search = _search.read(cx);
- let icon_style = theme.search.editor_icon.clone();
-
- // Editor Functionality
- let query = Flex::row()
- .with_child(
- Svg::for_style(icon_style.icon)
- .contained()
- .with_style(icon_style.container),
- )
- .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(),
+ let search_button_for_mode = |mode, side, cx: &mut ViewContext<ProjectSearchBar>| {
+ let is_active = if let Some(search) = self.active_project_search.as_ref() {
+ let search = search.read(cx);
+ search.current_mode == mode
+ } else {
+ false
+ };
+ render_search_mode_button(
+ mode,
+ side,
+ is_active,
+ move |_, this, cx| {
+ this.activate_search_mode(mode, cx);
+ },
+ cx,
)
- .align_children_center()
- .flex(1., true);
+ };
let search = _search.read(cx);
@@ -1486,50 +1486,6 @@ impl View for ProjectSearchBar {
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| {
Label::new(
format!(
@@ -1544,25 +1500,81 @@ impl View for ProjectSearchBar {
.aligned()
});
- let search_button_for_mode = |mode, cx: &mut ViewContext<ProjectSearchBar>| {
- let is_active = if let Some(search) = self.active_project_search.as_ref() {
- let search = search.read(cx);
- search.current_mode == mode
- } else {
- false
- };
- render_search_mode_button(
- mode,
- is_active,
- move |_, this, cx| {
- this.activate_search_mode(mode, cx);
- },
- cx,
+ let query_column = Flex::column()
+ .with_spacing(theme.search.search_row_spacing)
+ .with_child(
+ Flex::row()
+ .with_child(
+ Svg::for_style(icon_style.icon)
+ .contained()
+ .with_style(icon_style.container),
+ )
+ .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()
+ .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),
)
- };
- let is_active = search.active_match_index.is_some();
- let semantic_index = SemanticIndex::enabled(cx)
- .then(|| search_button_for_mode(SearchMode::Semantic, cx));
+ .with_children(search.filters_enabled.then(|| {
+ Flex::row()
+ .with_child(
+ 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>| {
render_nav_button(
label,
@@ -1578,43 +1590,17 @@ impl View for ProjectSearchBar {
};
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::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()
.with_height(theme.search.search_bar_row_height)
- .aligned()
- .right()
- .top()
.flex_float();
Flex::row()
- .with_child(editor_column)
- .with_child(nav_column)
+ .with_child(query_column)
.with_child(mode_column)
+ .with_child(nav_column)
.contained()
.with_style(theme.search.container)
.into_any_named("project search")
@@ -1637,7 +1623,7 @@ impl ToolbarItemView for ProjectSearchBar {
self.subscription = Some(cx.observe(&search, |_, _, cx| cx.notify()));
self.active_project_search = Some(search);
ToolbarItemLocation::PrimaryLeft {
- flex: Some((1., false)),
+ flex: Some((1., true)),
}
} else {
ToolbarItemLocation::Hidden
@@ -1645,13 +1631,12 @@ impl ToolbarItemView for ProjectSearchBar {
}
fn row_count(&self, cx: &ViewContext<Self>) -> usize {
- self.active_project_search
- .as_ref()
- .map(|search| {
- let offset = search.read(cx).filters_enabled as usize;
- 2 + offset
- })
- .unwrap_or_else(|| 2)
+ if let Some(search) = self.active_project_search.as_ref() {
+ if search.read(cx).filters_enabled {
+ return 2;
+ }
+ }
+ 1
}
}
@@ -13,34 +13,6 @@ use crate::{
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>(
icon: &'static str,
direction: Direction,
@@ -111,6 +83,7 @@ pub(super) fn render_nav_button<V: View>(
pub(crate) fn render_search_mode_button<V: View>(
mode: SearchMode,
+ side: Option<Side>,
is_active: bool,
on_click: impl Fn(MouseClick, &mut V, &mut EventContext<V>) + 'static,
cx: &mut ViewContext<V>,
@@ -119,41 +92,41 @@ pub(crate) fn render_search_mode_button<V: View>(
enum SearchModeButton {}
MouseEventHandler::new::<SearchModeButton, _>(mode.region_id(), cx, |state, cx| {
let theme = theme::current(cx);
- let mut style = theme
+ let style = theme
.search
.mode_button
.in_state(is_active)
.style_for(state)
.clone();
- style.container.border.left = mode.border_left();
- style.container.border.right = mode.border_right();
- let label = Label::new(mode.label(), style.text.clone())
- .aligned()
- .contained();
- let mut container_style = style.container.clone();
- if let Some(button_side) = mode.button_side() {
+ let mut container_style = style.container;
+ if let Some(button_side) = side {
if button_side == Side::Left {
+ container_style.border.left = true;
container_style.corner_radii = CornerRadii {
bottom_right: 0.,
top_right: 0.,
..container_style.corner_radii
};
- label.with_style(container_style)
} else {
+ container_style.border.left = false;
container_style.corner_radii = CornerRadii {
bottom_left: 0.,
top_left: 0.,
..container_style.corner_radii
};
- label.with_style(container_style)
}
} else {
+ container_style.border.left = false;
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)
.with_cursor_style(CursorStyle::PointingHand)
@@ -437,11 +437,11 @@ pub struct Search {
pub match_index: ContainedText,
pub major_results_status: TextStyle,
pub minor_results_status: TextStyle,
- pub dismiss_button: Interactive<IconButton>,
pub editor_icon: IconStyle,
pub mode_button: Toggleable<Interactive<ContainedText>>,
pub nav_button: Toggleable<Interactive<ContainedLabel>>,
pub search_bar_row_height: f32,
+ pub search_row_spacing: f32,
pub option_button_height: f32,
pub modes_container: ContainerStyle,
}
@@ -81,10 +81,7 @@ impl View for Toolbar {
ToolbarItemLocation::PrimaryLeft { flex } => {
primary_items_row_count = primary_items_row_count.max(item.row_count(cx));
- let left_item = ChildView::new(item.as_any(), cx)
- .aligned()
- .contained()
- .with_margin_right(spacing);
+ let left_item = ChildView::new(item.as_any(), cx).aligned();
if let Some((flex, expanded)) = flex {
primary_left_items.push(left_item.flex(flex, expanded).into_any());
} else {
@@ -94,11 +91,7 @@ impl View for Toolbar {
ToolbarItemLocation::PrimaryRight { flex } => {
primary_items_row_count = primary_items_row_count.max(item.row_count(cx));
- let right_item = ChildView::new(item.as_any(), cx)
- .aligned()
- .contained()
- .with_margin_left(spacing)
- .flex_float();
+ let right_item = ChildView::new(item.as_any(), cx).aligned().flex_float();
if let Some((flex, expanded)) = flex {
primary_right_items.push(right_item.flex(flex, expanded).into_any());
} else {
@@ -120,7 +113,7 @@ impl View for Toolbar {
let container_style = theme.container;
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_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),
- },
- })
-}
@@ -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
+ }
+}
@@ -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
color?: keyof Theme["lowest"]
margin?: Partial<Margin>
+ disabled?: boolean
text_properties?: TextProperties
}
@@ -29,6 +30,7 @@ export function text_button({
color,
layer,
margin,
+ disabled,
text_properties,
}: TextButtonOptions = {}) {
const theme = useTheme()
@@ -65,13 +67,17 @@ export function text_button({
state: {
default: {
background: background_color,
- color: foreground(layer ?? theme.lowest, color),
+ color:
+ disabled
+ ? foreground(layer ?? theme.lowest, "disabled")
+ : foreground(layer ?? theme.lowest, color),
},
- hovered: {
- background: background(layer ?? theme.lowest, color, "hovered"),
- color: foreground(layer ?? theme.lowest, color, "hovered"),
- },
- clicked: {
+ hovered:
+ disabled ? {} : {
+ background: background(layer ?? theme.lowest, color, "hovered"),
+ color: foreground(layer ?? theme.lowest, color, "hovered"),
+ },
+ clicked: disabled ? {} : {
background: background(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 { interactive, toggleable } from "../element"
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 {
const theme = useTheme()
+ const SEARCH_ROW_SPACING = 12
// Search input
const editor = {
@@ -34,12 +48,8 @@ export default function search(): any {
}
return {
- padding: { top: 16, bottom: 16, left: 16, right: 16 },
- // TODO: Add an activeMatchBackground on the rust side to differentiate between active and inactive
- match_background: with_opacity(
- foreground(theme.highest, "accent"),
- 0.4
- ),
+ padding: { top: 4, bottom: 4 },
+
option_button: toggleable({
base: interactive({
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({
- 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: {
- active: interactive({
- base: {
- ...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"),
- },
- },
- })
+ inactive: text_button({ variant: "ghost", layer: theme.highest, disabled: true, margin: { right: SEARCH_ROW_SPACING }, text_properties: { size: "sm" } }),
+ active: text_button({ variant: "ghost", layer: theme.highest, margin: { right: SEARCH_ROW_SPACING }, text_properties: { size: "sm" } })
}
}),
editor,
@@ -207,15 +183,15 @@ export default function search(): any {
border: border(theme.highest, "negative"),
},
match_index: {
- ...text(theme.highest, "mono", "variant"),
+ ...text(theme.highest, "mono", { size: "sm" }),
padding: {
- left: 9,
+ right: SEARCH_ROW_SPACING,
},
},
option_button_group: {
padding: {
- left: 12,
- right: 12,
+ left: SEARCH_ROW_SPACING,
+ right: SEARCH_ROW_SPACING,
},
},
include_exclude_inputs: {
@@ -232,52 +208,26 @@ export default function search(): any {
...text(theme.highest, "mono", "variant"),
size: 13,
},
- dismiss_button: interactive({
- 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")
- },
- },
- }),
+ // Input Icon
editor_icon: {
icon: {
- color: foreground(theme.highest, "variant"),
- asset: "icons/magnifying_glass_12.svg",
+ color: foreground(theme.highest, "disabled"),
+ asset: "icons/magnifying_glass.svg",
dimensions: {
- width: 12,
- height: 12,
+ width: 14,
+ height: 14,
}
},
container: {
- margin: { right: 6 },
- padding: { left: 2, right: 2 },
+ margin: { right: 4 },
+ padding: { left: 1, right: 1 },
}
},
+ // Toggle group buttons - Text | Regex | Semantic
mode_button: toggleable({
base: interactive({
base: {
- ...text(theme.highest, "mono", "variant"),
+ ...text(theme.highest, "mono", "variant", { size: "sm" }),
background: background(theme.highest, "variant"),
border: {
@@ -285,21 +235,24 @@ export default function search(): any {
left: false,
right: false
},
-
+ margin: {
+ top: 1,
+ bottom: 1,
+ },
padding: {
- left: 10,
- right: 10,
+ left: 12,
+ right: 12,
},
corner_radius: 6,
},
state: {
hovered: {
- ...text(theme.highest, "mono", "variant", "hovered"),
+ ...text(theme.highest, "mono", "variant", "hovered", { size: "sm" }),
background: background(theme.highest, "variant", "hovered"),
border: border(theme.highest, "on", "hovered"),
},
clicked: {
- ...text(theme.highest, "mono", "variant", "pressed"),
+ ...text(theme.highest, "mono", "variant", "pressed", { size: "sm" }),
background: background(theme.highest, "variant", "pressed"),
border: border(theme.highest, "on", "pressed"),
},
@@ -308,20 +261,23 @@ export default function search(): any {
state: {
active: {
default: {
- ...text(theme.highest, "mono", "on"),
+ ...text(theme.highest, "mono", "on", { size: "sm" }),
background: background(theme.highest, "on")
},
hovered: {
- ...text(theme.highest, "mono", "on", "hovered"),
+ ...text(theme.highest, "mono", "on", "hovered", { size: "sm" }),
background: background(theme.highest, "on", "hovered")
},
clicked: {
- ...text(theme.highest, "mono", "on", "pressed"),
+ ...text(theme.highest, "mono", "on", "pressed", { size: "sm" }),
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({
state: {
inactive: interactive({
@@ -334,7 +290,10 @@ export default function search(): any {
left: false,
right: false,
},
-
+ margin: {
+ top: 1,
+ bottom: 1,
+ },
padding: {
left: 10,
right: 10,
@@ -354,7 +313,10 @@ export default function search(): any {
left: false,
right: false,
},
-
+ margin: {
+ top: 1,
+ bottom: 1,
+ },
padding: {
left: 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,
- modes_container: {
- margin: {
- right: 9
- }
- }
-
+ modes_container: {},
+ ...search_results()
}
}
@@ -129,7 +129,7 @@ export default function workspace(): any {
status_bar: statusBar(),
titlebar: titlebar(),
toolbar: {
- height: 34,
+ height: 42,
background: background(theme.highest),
border: border(theme.highest, { bottom: true }),
item_spacing: 8,
@@ -138,7 +138,7 @@ export default function workspace(): any {
variant: "ghost",
active_color: "accent",
}),
- padding: { left: 8, right: 8, top: 4, bottom: 4 },
+ padding: { left: 8, right: 8 },
},
breadcrumb_height: 24,
breadcrumbs: interactive({
@@ -21,8 +21,7 @@
"experimentalDecorators": true,
"strictPropertyInitialization": false,
"skipLibCheck": true,
- "useUnknownInCatchVariables": false,
- "baseUrl": "."
+ "useUnknownInCatchVariables": false
},
"exclude": [
"node_modules"