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}