Skip to main content

modde_ui/views/
tabs.rs

1use crate::action_button::{ButtonAction, DescribedButtonExt};
2use crate::semantics;
3use crate::views::selectable_text::text;
4use iced::widget::{button, column, row};
5use iced::{Alignment, Element, Length, color};
6
7pub struct Tab {
8    pub label: String,
9    pub active: bool,
10    pub action: ButtonAction,
11    pub test_id: Option<String>,
12}
13
14impl Tab {
15    pub fn new(label: impl Into<String>, active: bool, action: ButtonAction) -> Self {
16        Self {
17            label: label.into(),
18            active,
19            action,
20            test_id: None,
21        }
22    }
23
24    #[must_use]
25    pub fn test_id(mut self, test_id: impl Into<String>) -> Self {
26        self.test_id = Some(test_id.into());
27        self
28    }
29}
30
31pub fn tab_bar(tabs: impl IntoIterator<Item = Tab>) -> Element<'static, crate::app::Message> {
32    tabs.into_iter()
33        .fold(row![].spacing(6), |bar, tab| {
34            let label = if tab.active {
35                text(tab.label.clone()).size(13).color(color!(0x8AB4FF))
36            } else {
37                text(tab.label.clone()).size(13)
38            };
39            let btn = button(label).padding([4, 10]).style(button::text);
40            let tab_button = if tab.active {
41                btn.described_disabled("This tab is already open.")
42            } else {
43                btn.on_action(tab.action)
44            };
45            let tab_button = if let Some(test_id) = tab.test_id {
46                semantics::test_id(test_id, tab_button)
47            } else {
48                tab_button
49            };
50            let indicator = if tab.active {
51                text("━━━━").size(10).color(color!(0x8AB4FF))
52            } else {
53                text("").size(10)
54            };
55            bar.push(
56                column![tab_button, indicator]
57                    .spacing(0)
58                    .align_x(Alignment::Center)
59                    .width(Length::Shrink),
60            )
61        })
62        .align_y(Alignment::Center)
63        .into()
64}