tab

Function tab 

Source
pub fn tab<IF, I, T, KF, K, VF, V>(
    active_fn: impl Fn() -> Option<usize> + 'static,
    each_fn: IF,
    key_fn: KF,
    view_fn: VF,
) -> Tab<T>
where IF: Fn() -> I + 'static, I: IntoIterator<Item = T>, KF: Fn(&T) -> K + 'static, K: Eq + Hash + 'static, VF: Fn(T) -> V + 'static, V: IntoView + 'static, T: 'static,
Expand description

A tab widget. Create tabs from static or dynamic lists.

§Simple example

// Tabs from static list:
let tabs = RwSignal::new(vec!["tab1, tab2, tab3"]);
let active_tab = RwSignal::new(0);

let side_bar = tabs
    .get()
    .into_iter()
    .enumerate()
    .map(move |(idx, item)| {
        item.style(move |s| s
            .height(36.)
            .apply_if(idx != active_tab.get(), |s| s.apply(theme::hover_style()))
        )
    })
    .list()
    .on_select(move |idx| {
        if let Some(idx) = idx {
            active_tab.set(idx);
        }
});

let static_tabs = tab(
    move || Some(active_tab.get()),
    move || tabs.get(),
    |it| *it,
    |tab_content| tab_content
        .container()
        .style(|s| s.size(150., 150.).padding(10.))
);

stack((side_bar, static_tabs));

§Complex example

// Tabs from dynamic list
#[derive(Clone)]
struct TabContent {
    idx: usize,
    name: String,
}

impl TabContent {
    fn new(tabs_count: usize) -> Self {
        Self {
            idx: tabs_count,
            name: format!("Tab with index"),
        }
    }
}

#[derive(Clone)]
enum Action {
    Add,
    Remove,
    None,
}
let tabs = RwSignal::new(vec![]);
let active_tab = RwSignal::new(None::<usize>);
let tab_action = RwSignal::new(Action::None);
create_effect(move |_| match tab_action.get() {
    Action::Add => {
        tabs.update(|tabs| tabs.push(TabContent::new(tabs.len())));
    }
    Action::Remove => {
        tabs.update(|tabs| { tabs.pop(); });
    }
    Action::None => ()
});///
let tabs_view = stack((dyn_stack(
    move || tabs.get(),
    |tab| tab.idx,
    move |tab| {
        text(format!("{} {}", tab.name, tab.idx)).button().style(move |s| s
            .width_full()
            .height(36.px())
            .apply_if(active_tab.get().is_some_and(|a| a == tab.idx), |s| {
                s.with_theme(|s, t| s.border_color(t.primary()))
            })
        )
        .on_click_stop(move |_| {
            active_tab.update(|a| {
                *a = Some(tab.idx);
            });
        })
    },
)
.style(|s| s.flex_col().width_full().row_gap(5.))
.scroll()
.on_click_stop(move |_| {
    if active_tab.with_untracked(|act| act.is_some()) {
        active_tab.set(None)
    }
})
.style(|s| s.size_full().padding(5.).padding_right(7.))
.scroll_style(|s| s.handle_thickness(6.).shrink_to_fit()),))
.style(|s| s
    .width(140.)
    .min_width(140.)
    .height_full()
    .border_right(1.)
    .with_theme(|s, t| s.border_color(t.border_muted()))
);
let tabs_content_view = stack((
    tab(
        move || active_tab.get(),
        move || tabs.get(),
        |tab| tab.idx,
        move |tab| {
         v_stack((
            label(move || format!("{}", tab.name)).style(|s| s
                .font_size(15.)
                .font_bold()),
            label(move || format!("{}", tab.idx)).style(|s| s
                .font_size(20.)
                .font_bold()),
            label(move || "is now active").style(|s| s
                .font_size(13.)),
        )).style(|s| s
            .size(150.px(), 150.px())
            .items_center()
            .justify_center()
            .row_gap(10.))
        },
    ).style(|s| s.size_full()),
))
.style(|s| s.size_full());