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