tab_bar.rs

  1use crate::prelude::*;
  2use crate::{Icon, IconButton, Tab};
  3
  4#[derive(Component)]
  5pub struct TabBar {
  6    id: ElementId,
  7    /// Backwards, Forwards
  8    can_navigate: (bool, bool),
  9    tabs: Vec<Tab>,
 10}
 11
 12impl TabBar {
 13    pub fn new(id: impl Into<ElementId>, tabs: Vec<Tab>) -> Self {
 14        Self {
 15            id: id.into(),
 16            can_navigate: (false, false),
 17            tabs,
 18        }
 19    }
 20
 21    pub fn can_navigate(mut self, can_navigate: (bool, bool)) -> Self {
 22        self.can_navigate = can_navigate;
 23        self
 24    }
 25
 26    fn render<V: 'static>(self, _view: &mut V, cx: &mut ViewContext<V>) -> impl Component<V> {
 27        let (can_navigate_back, can_navigate_forward) = self.can_navigate;
 28
 29        div()
 30            .id(self.id.clone())
 31            .w_full()
 32            .flex()
 33            .bg(cx.theme().colors().tab_bar)
 34            // Left Side
 35            .child(
 36                div()
 37                    .px_1()
 38                    .flex()
 39                    .flex_none()
 40                    .gap_2()
 41                    // Nav Buttons
 42                    .child(
 43                        div()
 44                            .flex()
 45                            .items_center()
 46                            .gap_px()
 47                            .child(
 48                                IconButton::new("arrow_left", Icon::ArrowLeft)
 49                                    .state(InteractionState::Enabled.if_enabled(can_navigate_back)),
 50                            )
 51                            .child(
 52                                IconButton::new("arrow_right", Icon::ArrowRight).state(
 53                                    InteractionState::Enabled.if_enabled(can_navigate_forward),
 54                                ),
 55                            ),
 56                    ),
 57            )
 58            .child(
 59                div().w_0().flex_1().h_full().child(
 60                    div()
 61                        .id("tabs")
 62                        .flex()
 63                        .overflow_x_scroll()
 64                        .children(self.tabs.clone()),
 65                ),
 66            )
 67            // Right Side
 68            .child(
 69                div()
 70                    .px_1()
 71                    .flex()
 72                    .flex_none()
 73                    .gap_2()
 74                    // Nav Buttons
 75                    .child(
 76                        div()
 77                            .flex()
 78                            .items_center()
 79                            .gap_px()
 80                            .child(IconButton::new("plus", Icon::Plus))
 81                            .child(IconButton::new("split", Icon::Split)),
 82                    ),
 83            )
 84    }
 85}
 86
 87use gpui2::ElementId;
 88#[cfg(feature = "stories")]
 89pub use stories::*;
 90
 91#[cfg(feature = "stories")]
 92mod stories {
 93    use super::*;
 94    use crate::Story;
 95    use gpui2::{Div, Render};
 96
 97    pub struct TabBarStory;
 98
 99    impl Render for TabBarStory {
100        type Element = Div<Self>;
101
102        fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
103            Story::container(cx)
104                .child(Story::title_for::<_, TabBar>(cx))
105                .child(Story::label(cx, "Default"))
106                .child(TabBar::new(
107                    "tab-bar",
108                    vec![
109                        Tab::new(1)
110                            .title("Cargo.toml".to_string())
111                            .current(false)
112                            .git_status(GitStatus::Modified),
113                        Tab::new(2)
114                            .title("Channels Panel".to_string())
115                            .current(false),
116                        Tab::new(3)
117                            .title("channels_panel.rs".to_string())
118                            .current(true)
119                            .git_status(GitStatus::Modified),
120                        Tab::new(4)
121                            .title("workspace.rs".to_string())
122                            .current(false)
123                            .git_status(GitStatus::Modified),
124                        Tab::new(5)
125                            .title("icon_button.rs".to_string())
126                            .current(false),
127                        Tab::new(6)
128                            .title("storybook.rs".to_string())
129                            .current(false)
130                            .git_status(GitStatus::Created),
131                        Tab::new(7).title("theme.rs".to_string()).current(false),
132                        Tab::new(8)
133                            .title("theme_registry.rs".to_string())
134                            .current(false),
135                        Tab::new(9)
136                            .title("styleable_helpers.rs".to_string())
137                            .current(false),
138                    ],
139                ))
140        }
141    }
142}