WIP styling

Piotr Osiewicz and Nate created

Co-authored-by: Nate <nate@zed.dev>

Change summary

crates/editor2/src/items.rs         |  2 
crates/search2/src/buffer_search.rs | 29 +++++++---------
crates/search2/src/search_bar.rs    | 38 ++++++++++++++--------
crates/workspace2/src/toolbar.rs    | 53 ++++++++++++++++++++++++++++--
4 files changed, 85 insertions(+), 37 deletions(-)

Detailed changes

crates/editor2/src/items.rs 🔗

@@ -760,7 +760,7 @@ impl Item for Editor {
     }
 
     fn breadcrumb_location(&self) -> ToolbarItemLocation {
-        ToolbarItemLocation::PrimaryLeft { flex: None }
+        ToolbarItemLocation::PrimaryLeft
     }
 
     fn breadcrumbs(&self, variant: &Theme, cx: &AppContext) -> Option<Vec<BreadcrumbText>> {

crates/search2/src/buffer_search.rs 🔗

@@ -10,16 +10,16 @@ use collections::HashMap;
 use editor::Editor;
 use futures::channel::oneshot;
 use gpui::{
-    action, actions, blue, div, red, white, Action, AnyElement, AnyView, AppContext, Component,
-    Div, Entity, EventEmitter, Hsla, ParentElement as _, Render, Styled, Subscription, Svg, Task,
-    View, ViewContext, VisualContext as _, WindowContext,
+    action, actions, blue, div, red, rems, white, Action, AnyElement, AnyView, AppContext,
+    Component, Div, Entity, EventEmitter, Hsla, ParentElement as _, Render, Styled, Subscription,
+    Svg, Task, View, ViewContext, VisualContext as _, WindowContext,
 };
 use project::search::SearchQuery;
 use serde::Deserialize;
 use std::{any::Any, sync::Arc};
 use theme::ActiveTheme;
 
-use ui::{h_stack, Icon, IconButton, IconElement, Label, StyledExt};
+use ui::{h_stack, Button, ButtonGroup, Icon, IconButton, IconElement, Label, StyledExt};
 use util::ResultExt;
 use workspace::{
     item::ItemHandle,
@@ -173,10 +173,9 @@ impl Render for BufferSearchBar {
             )
         };
         div()
-            .w_full()
             .border()
             .border_color(blue())
-            .flex() // Make this div a flex container
+            .flex()
             .justify_between()
             .child(
                 div()
@@ -199,17 +198,10 @@ impl Render for BufferSearchBar {
                             .then(|| search_option_button(SearchOptions::WHOLE_WORD)),
                     ),
             )
-            .child(div().w_auto().flex_row())
-            .child(search_button_for_mode(
-                SearchMode::Text,
-                Some(Side::Left),
-                cx,
-            ))
-            .child(search_button_for_mode(
-                SearchMode::Regex,
-                Some(Side::Right),
-                cx,
-            ))
+            .child(ButtonGroup::new(vec![
+                search_button_for_mode(SearchMode::Text, Some(Side::Left), cx),
+                search_button_for_mode(SearchMode::Regex, Some(Side::Right), cx),
+            ]))
             .when(supported_options.replacement, |this| {
                 this.child(super::toggle_replace_button(self.replace_enabled))
             })
@@ -373,6 +365,9 @@ impl BufferSearchBar {
         workspace.register_action(|workspace, a: &Deploy, cx| {
             workspace.active_pane().update(cx, |this, cx| {
                 this.toolbar().update(cx, |this, cx| {
+                    if this.item_of_type::<BufferSearchBar>().is_some() {
+                        return;
+                    }
                     let view = cx.build_view(|cx| BufferSearchBar::new(cx));
                     this.add_item(view.clone(), cx);
                     view.update(cx, |this, cx| this.deploy(a, cx));

crates/search2/src/search_bar.rs 🔗

@@ -5,7 +5,7 @@ use gpui::{
     ParentElement as _, StatelessInteractive, Styled, Svg, View, ViewContext,
 };
 use theme::ActiveTheme;
-use ui::{Button, Label};
+use ui::{v_stack, Button, ButtonVariant, Label};
 use workspace::searchable::Direction;
 
 use crate::{
@@ -83,23 +83,33 @@ pub(crate) fn render_search_mode_button<V: 'static>(
     mode: SearchMode,
     side: Option<Side>,
     is_active: bool,
-    on_click: impl Fn(&mut V, &mut ViewContext<V>) + 'static,
+    on_click: impl Fn(&mut V, &mut ViewContext<V>) + 'static + Send + Sync,
     cx: &mut ViewContext<V>,
-) -> impl Component<V> {
+) -> Button<V> {
     //let tooltip_style = cx.theme().tooltip.clone();
     enum SearchModeButton {}
 
-    div()
-        .border_2()
-        .rounded_md()
-        .when(side == Some(Side::Left), |this| {
-            this.border_r_0().rounded_tr_none().rounded_br_none()
-        })
-        .when(side == Some(Side::Right), |this| {
-            this.border_l_0().rounded_bl_none().rounded_tl_none()
-        })
-        .on_key_down(move |v, _, _, cx| on_click(v, cx))
-        .child(Label::new(mode.label()))
+    let button_variant = if is_active {
+        ButtonVariant::Filled
+    } else {
+        ButtonVariant::Ghost
+    };
+
+    Button::new(mode.label())
+        .on_click(Arc::new(on_click))
+        .variant(button_variant)
+
+    // v_stack()
+    //     .border_2()
+    //     .rounded_md()
+    //     .when(side == Some(Side::Left), |this| {
+    //         this.border_r_0().rounded_tr_none().rounded_br_none()
+    //     })
+    //     .when(side == Some(Side::Right), |this| {
+    //         this.border_l_0().rounded_bl_none().rounded_tl_none()
+    //     })
+    //     .on_key_down(move |v, _, _, cx| on_click(v, cx))
+    //     .child(Label::new(mode.label()))
     // MouseEventHandler::new::<SearchModeButton, _>(mode.region_id(), cx, |state, cx| {
     //     let theme = cx.theme();
     //     let style = theme

crates/workspace2/src/toolbar.rs 🔗

@@ -1,8 +1,9 @@
 use crate::ItemHandle;
 use gpui::{
-    div, AnyView, Div, Entity, EntityId, EventEmitter, ParentElement, Render, Styled, View,
-    ViewContext, WindowContext,
+    div, AnyView, Component, Div, Entity, EntityId, EventEmitter, ParentElement, Render, Styled,
+    View, ViewContext, WindowContext,
 };
+use ui::{h_stack, v_stack, Button, Icon, IconButton, Label, LabelColor, StyledExt};
 
 pub enum ToolbarItemEvent {
     ChangeLocation(ToolbarItemLocation),
@@ -40,8 +41,8 @@ trait ToolbarItemViewHandle: Send {
 #[derive(Copy, Clone, Debug, PartialEq)]
 pub enum ToolbarItemLocation {
     Hidden,
-    PrimaryLeft { flex: Option<(f32, bool)> },
-    PrimaryRight { flex: Option<(f32, bool)> },
+    PrimaryLeft,
+    PrimaryRight,
     Secondary,
 }
 
@@ -52,12 +53,54 @@ pub struct Toolbar {
     items: Vec<(Box<dyn ToolbarItemViewHandle>, ToolbarItemLocation)>,
 }
 
+impl Toolbar {
+    fn left_items(&self) -> impl Iterator<Item = &dyn ToolbarItemViewHandle> {
+        self.items.iter().filter_map(|(item, location)| {
+            if *location == ToolbarItemLocation::PrimaryLeft {
+                Some(item.as_ref())
+            } else {
+                None
+            }
+        })
+    }
+
+    fn right_items(&self) -> impl Iterator<Item = &dyn ToolbarItemViewHandle> {
+        self.items.iter().filter_map(|(item, location)| {
+            if *location == ToolbarItemLocation::PrimaryRight {
+                Some(item.as_ref())
+            } else {
+                None
+            }
+        })
+    }
+}
+
 impl Render for Toolbar {
     type Element = Div<Self>;
 
     fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
         //dbg!(&self.items.len());
-        div().children(self.items.iter().map(|(child, _)| child.to_any()))
+        v_stack()
+            .child(
+                h_stack()
+                    .justify_between()
+                    .child(
+                        // Toolbar left side
+                        h_stack()
+                            .p_1()
+                            .child(Button::new("crates"))
+                            .child(Label::new("/").color(LabelColor::Muted))
+                            .child(Button::new("workspace2")),
+                    )
+                    // Toolbar right side
+                    .child(
+                        h_stack()
+                            .p_1()
+                            .child(IconButton::new("buffer-search", Icon::MagnifyingGlass))
+                            .child(IconButton::new("inline-assist", Icon::MagicWand)),
+                    ),
+            )
+            .children(self.items.iter().map(|(child, _)| child.to_any()))
     }
 }