tab_bar.rs

  1use std::marker::PhantomData;
  2
  3use crate::prelude::*;
  4use crate::{theme, Icon, IconButton, Tab};
  5
  6#[derive(Element)]
  7pub struct TabBar<S: 'static + Send + Sync + Clone> {
  8    state_type: PhantomData<S>,
  9    scroll_state: ScrollState,
 10    tabs: Vec<Tab<S>>,
 11}
 12
 13impl<S: 'static + Send + Sync + Clone> TabBar<S> {
 14    pub fn new(tabs: Vec<Tab<S>>) -> Self {
 15        Self {
 16            state_type: PhantomData,
 17            scroll_state: ScrollState::default(),
 18            tabs,
 19        }
 20    }
 21
 22    pub fn bind_scroll_state(&mut self, scroll_state: ScrollState) {
 23        self.scroll_state = scroll_state;
 24    }
 25
 26    fn render(&mut self, _view: &mut S, cx: &mut ViewContext<S>) -> impl Element<ViewState = S> {
 27        let theme = theme(cx);
 28        let can_navigate_back = true;
 29        let can_navigate_forward = false;
 30
 31        div()
 32            .w_full()
 33            .flex()
 34            .bg(theme.middle.base.default.background)
 35            // Left Side
 36            .child(
 37                div()
 38                    .px_1()
 39                    .flex()
 40                    .flex_none()
 41                    .gap_2()
 42                    // Nav Buttons
 43                    .child(
 44                        div()
 45                            .flex()
 46                            .items_center()
 47                            .gap_px()
 48                            .child(
 49                                IconButton::new(Icon::ArrowLeft)
 50                                    .state(InteractionState::Enabled.if_enabled(can_navigate_back)),
 51                            )
 52                            .child(
 53                                IconButton::new(Icon::ArrowRight).state(
 54                                    InteractionState::Enabled.if_enabled(can_navigate_forward),
 55                                ),
 56                            ),
 57                    ),
 58            )
 59            .child(
 60                div().w_0().flex_1().h_full().child(
 61                    div()
 62                        .flex()
 63                        .overflow_x_scroll(self.scroll_state.clone())
 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(Icon::Plus))
 81                            .child(IconButton::new(Icon::Split)),
 82                    ),
 83            )
 84    }
 85}
 86
 87#[cfg(feature = "stories")]
 88pub use stories::*;
 89
 90#[cfg(feature = "stories")]
 91mod stories {
 92    use crate::Story;
 93
 94    use super::*;
 95
 96    #[derive(Element)]
 97    pub struct TabBarStory<S: 'static + Send + Sync + Clone> {
 98        state_type: PhantomData<S>,
 99    }
100
101    impl<S: 'static + Send + Sync + Clone> TabBarStory<S> {
102        pub fn new() -> Self {
103            Self {
104                state_type: PhantomData,
105            }
106        }
107
108        fn render(
109            &mut self,
110            _view: &mut S,
111            cx: &mut ViewContext<S>,
112        ) -> impl Element<ViewState = S> {
113            Story::container(cx)
114                .child(Story::title_for::<_, TabBar<S>>(cx))
115                .child(Story::label(cx, "Default"))
116                .child(TabBar::new(vec![
117                    Tab::new()
118                        .title("Cargo.toml".to_string())
119                        .current(false)
120                        .git_status(GitStatus::Modified),
121                    Tab::new()
122                        .title("Channels Panel".to_string())
123                        .current(false),
124                    Tab::new()
125                        .title("channels_panel.rs".to_string())
126                        .current(true)
127                        .git_status(GitStatus::Modified),
128                    Tab::new()
129                        .title("workspace.rs".to_string())
130                        .current(false)
131                        .git_status(GitStatus::Modified),
132                    Tab::new()
133                        .title("icon_button.rs".to_string())
134                        .current(false),
135                    Tab::new()
136                        .title("storybook.rs".to_string())
137                        .current(false)
138                        .git_status(GitStatus::Created),
139                    Tab::new().title("theme.rs".to_string()).current(false),
140                    Tab::new()
141                        .title("theme_registry.rs".to_string())
142                        .current(false),
143                    Tab::new()
144                        .title("styleable_helpers.rs".to_string())
145                        .current(false),
146                ]))
147        }
148    }
149}