toolbar.rs

  1use gpui3::AnyElement;
  2use smallvec::SmallVec;
  3
  4use crate::prelude::*;
  5use crate::theme;
  6
  7#[derive(Clone)]
  8pub struct ToolbarItem {}
  9
 10#[derive(Element)]
 11pub struct Toolbar<S: 'static + Send + Sync> {
 12    left_items: SmallVec<[AnyElement<S>; 2]>,
 13    right_items: SmallVec<[AnyElement<S>; 2]>,
 14}
 15
 16impl<S: 'static + Send + Sync> Toolbar<S> {
 17    pub fn new() -> Self {
 18        Self {
 19            left_items: SmallVec::new(),
 20            right_items: SmallVec::new(),
 21        }
 22    }
 23
 24    pub fn left_item(mut self, child: impl IntoAnyElement<S>) -> Self
 25    where
 26        Self: Sized,
 27    {
 28        self.left_items.push(child.into_any());
 29        self
 30    }
 31
 32    pub fn left_items(mut self, iter: impl IntoIterator<Item = impl IntoAnyElement<S>>) -> Self
 33    where
 34        Self: Sized,
 35    {
 36        self.left_items
 37            .extend(iter.into_iter().map(|item| item.into_any()));
 38        self
 39    }
 40
 41    pub fn right_item(mut self, child: impl IntoAnyElement<S>) -> Self
 42    where
 43        Self: Sized,
 44    {
 45        self.right_items.push(child.into_any());
 46        self
 47    }
 48
 49    pub fn right_items(mut self, iter: impl IntoIterator<Item = impl IntoAnyElement<S>>) -> Self
 50    where
 51        Self: Sized,
 52    {
 53        self.right_items
 54            .extend(iter.into_iter().map(|item| item.into_any()));
 55        self
 56    }
 57
 58    fn render(&mut self, _view: &mut S, cx: &mut ViewContext<S>) -> impl Element<ViewState = S> {
 59        let theme = theme(cx);
 60
 61        div()
 62            .bg(theme.highest.base.default.background)
 63            .p_2()
 64            .flex()
 65            .justify_between()
 66            .child(div().flex().children(self.left_items.drain(..)))
 67            .child(div().flex().children(self.right_items.drain(..)))
 68    }
 69}
 70
 71#[cfg(feature = "stories")]
 72pub use stories::*;
 73
 74#[cfg(feature = "stories")]
 75mod stories {
 76    use std::marker::PhantomData;
 77    use std::path::PathBuf;
 78    use std::str::FromStr;
 79
 80    use crate::{Breadcrumb, HighlightedText, Icon, IconButton, Story, Symbol};
 81
 82    use super::*;
 83
 84    #[derive(Element)]
 85    pub struct ToolbarStory<S: 'static + Send + Sync + Clone> {
 86        state_type: PhantomData<S>,
 87    }
 88
 89    impl<S: 'static + Send + Sync + Clone> ToolbarStory<S> {
 90        pub fn new() -> Self {
 91            Self {
 92                state_type: PhantomData,
 93            }
 94        }
 95
 96        fn render(
 97            &mut self,
 98            _view: &mut S,
 99            cx: &mut ViewContext<S>,
100        ) -> impl Element<ViewState = S> {
101            let theme = theme(cx);
102
103            Story::container(cx)
104                .child(Story::title_for::<_, Toolbar<S>>(cx))
105                .child(Story::label(cx, "Default"))
106                .child(
107                    Toolbar::new()
108                        .left_item(Breadcrumb::new(
109                            PathBuf::from_str("crates/ui/src/components/toolbar.rs").unwrap(),
110                            vec![
111                                Symbol(vec![
112                                    HighlightedText {
113                                        text: "impl ".to_string(),
114                                        color: HighlightColor::Keyword.hsla(&theme),
115                                    },
116                                    HighlightedText {
117                                        text: "ToolbarStory".to_string(),
118                                        color: HighlightColor::Function.hsla(&theme),
119                                    },
120                                ]),
121                                Symbol(vec![
122                                    HighlightedText {
123                                        text: "fn ".to_string(),
124                                        color: HighlightColor::Keyword.hsla(&theme),
125                                    },
126                                    HighlightedText {
127                                        text: "render".to_string(),
128                                        color: HighlightColor::Function.hsla(&theme),
129                                    },
130                                ]),
131                            ],
132                        ))
133                        .right_items(vec![
134                            IconButton::new(Icon::InlayHint),
135                            IconButton::new(Icon::MagnifyingGlass),
136                            IconButton::new(Icon::MagicWand),
137                        ]),
138                )
139        }
140    }
141}