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 super::*;
 96    use crate::Story;
 97    use gpui2::{Div, Render};
 98
 99    pub struct TabBarStory;
100
101    impl Render for TabBarStory {
102        type Element = Div<Self>;
103
104        fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
105            Story::container(cx)
106                .child(Story::title_for::<_, TabBar>(cx))
107                .child(Story::label(cx, "Default"))
108                .child(TabBar::new(
109                    "tab-bar",
110                    vec![
111                        Tab::new(1)
112                            .title("Cargo.toml".to_string())
113                            .current(false)
114                            .git_status(GitStatus::Modified),
115                        Tab::new(2)
116                            .title("Channels Panel".to_string())
117                            .current(false),
118                        Tab::new(3)
119                            .title("channels_panel.rs".to_string())
120                            .current(true)
121                            .git_status(GitStatus::Modified),
122                        Tab::new(4)
123                            .title("workspace.rs".to_string())
124                            .current(false)
125                            .git_status(GitStatus::Modified),
126                        Tab::new(5)
127                            .title("icon_button.rs".to_string())
128                            .current(false),
129                        Tab::new(6)
130                            .title("storybook.rs".to_string())
131                            .current(false)
132                            .git_status(GitStatus::Created),
133                        Tab::new(7).title("theme.rs".to_string()).current(false),
134                        Tab::new(8)
135                            .title("theme_registry.rs".to_string())
136                            .current(false),
137                        Tab::new(9)
138                            .title("styleable_helpers.rs".to_string())
139                            .current(false),
140                    ],
141                ))
142        }
143    }
144}