Skip to main content

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 a dynamic list using current APIs.
#[derive(Clone)]
struct TabContent {
    idx: usize,
    name: String,
}

#[derive(Clone, Copy)]
enum Action {
    Add,
    Remove,
    None,
}

let tabs = RwSignal::new(Vec::<TabContent>::new());
let active_tab = RwSignal::new(Some(0usize));
let tab_action = RwSignal::new(Action::None);

Effect::new(move |_| match tab_action.get() {
    Action::Add => {
        tabs.update(|tabs| {
            let idx = tabs.len();
            tabs.push(TabContent {
                idx,
                name: format!("Tab {idx}"),
            });
        });
        tab_action.set(Action::None);
    }
    Action::Remove => {
        tabs.update(|tabs| {
            tabs.pop();
        });
        tab_action.set(Action::None);
    }
    Action::None => {}
});

let tabs_view = dyn_stack(
    move || tabs.get(),
    |tab| tab.idx,
    move |tab| {
        let idx = tab.idx;
        Label::new(format!("{} {}", tab.name, tab.idx))
            .style(move |s| {
                s.width_full()
                    .height(36.0)
                    .apply_if(active_tab.get() == Some(idx), |s| s.font_bold())
            })
            .on_event_stop(listener::Click, move |_cx, _| active_tab.set(Some(idx)))
    },
)
.scroll()
.style(|s| s.width(140.).height_full().padding(5.0));

let tabs_content_view = tab(
    move || active_tab.get(),
    move || tabs.get(),
    |tab| tab.idx,
    move |tab| {
        Stack::vertical((
            Label::new(tab.name.clone()).style(|s| s.font_size(15.0).font_bold()),
            Label::new(format!("{}", tab.idx)).style(|s| s.font_size(20.0).font_bold()),
            Label::new("is now active"),
        ))
        .style(|s| {
            s.size(150.0, 150.0)
                .items_center()
                .justify_center()
                .row_gap(10.0)
        })
    },
);

let controls = Stack::new((
    Button::new("Add tab").on_event_stop(listener::Click, move |_cx, _| {
        tab_action.set(Action::Add)
    }),
    Button::new("Remove tab").on_event_stop(listener::Click, move |_cx, _| {
        tab_action.set(Action::Remove)
    }),
));

let _layout = Stack::vertical((controls, Stack::new((tabs_view, tabs_content_view))))
    .style(|s| s.size_full().row_gap(10.0));