perspective_viewer/components/containers/
tab_list.rs1use yew::{Callback, Children, Component, Html, Properties, classes, html};
14
15use crate::presentation::ColumnTab;
16
17#[derive(Properties, Debug, PartialEq)]
18pub struct TabListProps<T: ColumnTab> {
19 pub tabs: Vec<T>,
21
22 pub on_tab_change: Callback<(usize, T)>,
24
25 pub selected_tab: Option<usize>,
27
28 pub children: Children,
30}
31
32pub enum TabListMsg {
33 SetSelected(usize),
34}
35
36pub struct TabList<T: ColumnTab> {
37 t: std::marker::PhantomData<T>,
38 selected_idx: usize,
39}
40
41impl<T: ColumnTab> Component for TabList<T> {
42 type Message = TabListMsg;
43 type Properties = TabListProps<T>;
44
45 fn create(_ctx: &yew::Context<Self>) -> Self {
46 Self {
47 t: std::marker::PhantomData,
48 selected_idx: 0,
49 }
50 }
51
52 fn update(&mut self, ctx: &yew::Context<Self>, msg: Self::Message) -> bool {
53 match msg {
54 TabListMsg::SetSelected(idx) => {
55 ctx.props()
56 .on_tab_change
57 .emit((idx, ctx.props().tabs[idx].clone()));
58 self.selected_idx = idx;
59 true
60 },
61 }
62 }
63
64 fn changed(&mut self, ctx: &yew::Context<Self>, _old_props: &Self::Properties) -> bool {
65 self.selected_idx = ctx.props().selected_tab.unwrap_or_default();
66 true
67 }
68
69 fn view(&self, ctx: &yew::Context<Self>) -> Html {
70 let p = ctx.props();
71 let gutter_tabs = p.tabs.iter().enumerate().map(|(idx, tab)| {
72 let mut class = classes!("settings_tab");
73 if idx == self.selected_idx {
74 class.push("selected_tab");
75 }
76
77 let onclick = ctx.link().callback(move |_| TabListMsg::SetSelected(idx));
78 html! {
79 <span {class} {onclick}>
80 <div class="tab-title" id={tab.to_string()} />
81 <div class="tab-border" />
82 </span>
83 }
84 });
85
86 html! {
87 <>
88 <div id="settings_tab_bar">{ for gutter_tabs }</div>
89 <div id="format-tab" class="tab-content scrollable">
90 { ctx.props().children.iter().nth(self.selected_idx) }
91 </div>
92 </>
93 }
94 }
95}