mirror of
https://github.com/adoyle0/thaw.git
synced 2025-01-22 22:09:22 -05:00
refactor: tab
This commit is contained in:
parent
938342ab1f
commit
e8942dc212
11 changed files with 95 additions and 93 deletions
|
@ -82,8 +82,8 @@ fn TheRouter(is_routing: RwSignal<bool>) -> impl IntoView {
|
||||||
<Route path="/spin-button" view=SpinButtonMdPage/>
|
<Route path="/spin-button" view=SpinButtonMdPage/>
|
||||||
<Route path="/spinner" view=SpinnerMdPage/>
|
<Route path="/spinner" view=SpinnerMdPage/>
|
||||||
<Route path="/switch" view=SwitchMdPage/>
|
<Route path="/switch" view=SwitchMdPage/>
|
||||||
|
<Route path="/tab-list" view=TabListMdPage/>
|
||||||
<Route path="/table" view=TableMdPage/>
|
<Route path="/table" view=TableMdPage/>
|
||||||
<Route path="/tabs" view=TabsMdPage/>
|
|
||||||
<Route path="/tag" view=TagMdPage/>
|
<Route path="/tag" view=TagMdPage/>
|
||||||
<Route path="/text" view=TextMdPage/>
|
<Route path="/text" view=TextMdPage/>
|
||||||
<Route path="/time-picker" view=TimePickerMdPage/>
|
<Route path="/time-picker" view=TimePickerMdPage/>
|
||||||
|
|
|
@ -175,6 +175,10 @@ pub(crate) fn gen_menu_data() -> Vec<MenuGroupOption> {
|
||||||
value: "/components/spinner".into(),
|
value: "/components/spinner".into(),
|
||||||
label: "Spinner".into(),
|
label: "Spinner".into(),
|
||||||
},
|
},
|
||||||
|
MenuItemOption {
|
||||||
|
value: "/components/tab-list".into(),
|
||||||
|
label: "Tab List".into(),
|
||||||
|
},
|
||||||
MenuItemOption {
|
MenuItemOption {
|
||||||
value: "/components/tag".into(),
|
value: "/components/tag".into(),
|
||||||
label: "Tag".into(),
|
label: "Tag".into(),
|
||||||
|
@ -251,10 +255,6 @@ pub(crate) fn gen_menu_data() -> Vec<MenuGroupOption> {
|
||||||
value: "/components/loading-bar".into(),
|
value: "/components/loading-bar".into(),
|
||||||
label: "Loading Bar".into(),
|
label: "Loading Bar".into(),
|
||||||
},
|
},
|
||||||
MenuItemOption {
|
|
||||||
value: "/components/tabs".into(),
|
|
||||||
label: "Tabs".into(),
|
|
||||||
},
|
|
||||||
MenuItemOption {
|
MenuItemOption {
|
||||||
value: "/components/alert".into(),
|
value: "/components/alert".into(),
|
||||||
label: "Alert".into(),
|
label: "Alert".into(),
|
||||||
|
|
|
@ -6,10 +6,16 @@ let selected_value = RwSignal::new(String::new());
|
||||||
view! {
|
view! {
|
||||||
<TabList selected_value>
|
<TabList selected_value>
|
||||||
<Tab value="apple">
|
<Tab value="apple">
|
||||||
"🍎 Apple"
|
"Apple"
|
||||||
</Tab>
|
</Tab>
|
||||||
<Tab value="pear">
|
<Tab value="pear">
|
||||||
"🍐 Pear"
|
"Pear"
|
||||||
|
</Tab>
|
||||||
|
<Tab value="item1">
|
||||||
|
"Item 1"
|
||||||
|
</Tab>
|
||||||
|
<Tab value="item2">
|
||||||
|
"Item 2"
|
||||||
</Tab>
|
</Tab>
|
||||||
</TabList>
|
</TabList>
|
||||||
}
|
}
|
|
@ -64,8 +64,8 @@ pub fn include_md(_token_stream: proc_macro::TokenStream) -> proc_macro::TokenSt
|
||||||
"SpinButtonMdPage" => "../docs/spin_button/mod.md",
|
"SpinButtonMdPage" => "../docs/spin_button/mod.md",
|
||||||
"SpinnerMdPage" => "../docs/spinner/mod.md",
|
"SpinnerMdPage" => "../docs/spinner/mod.md",
|
||||||
"SwitchMdPage" => "../docs/switch/mod.md",
|
"SwitchMdPage" => "../docs/switch/mod.md",
|
||||||
|
"TabListMdPage" => "../docs/tab_list/mod.md",
|
||||||
"TableMdPage" => "../docs/table/mod.md",
|
"TableMdPage" => "../docs/table/mod.md",
|
||||||
"TabsMdPage" => "../docs/tabs/mod.md",
|
|
||||||
"TagMdPage" => "../docs/tag/mod.md",
|
"TagMdPage" => "../docs/tag/mod.md",
|
||||||
"TimePickerMdPage" => "../docs/time_picker/mod.md",
|
"TimePickerMdPage" => "../docs/time_picker/mod.md",
|
||||||
"TextMdPage" => "../docs/text/mod.md",
|
"TextMdPage" => "../docs/text/mod.md",
|
||||||
|
|
|
@ -38,7 +38,7 @@ mod spin_button;
|
||||||
mod spinner;
|
mod spinner;
|
||||||
mod switch;
|
mod switch;
|
||||||
mod table;
|
mod table;
|
||||||
mod tabs;
|
mod tab_list;
|
||||||
mod tag;
|
mod tag;
|
||||||
mod text;
|
mod text;
|
||||||
mod theme;
|
mod theme;
|
||||||
|
@ -84,7 +84,7 @@ pub use spin_button::*;
|
||||||
pub use spinner::*;
|
pub use spinner::*;
|
||||||
pub use switch::*;
|
pub use switch::*;
|
||||||
pub use table::*;
|
pub use table::*;
|
||||||
pub use tabs::*;
|
pub use tab_list::*;
|
||||||
pub use tag::*;
|
pub use tag::*;
|
||||||
pub use text::*;
|
pub use text::*;
|
||||||
pub use thaw_utils::{create_component_ref, ComponentRef, SignalWatch};
|
pub use thaw_utils::{create_component_ref, ComponentRef, SignalWatch};
|
||||||
|
|
77
thaw/src/tab_list/tab.rs
Normal file
77
thaw/src/tab_list/tab.rs
Normal file
|
@ -0,0 +1,77 @@
|
||||||
|
use super::{TabListInjection, TabRegisterData};
|
||||||
|
use leptos::*;
|
||||||
|
use std::ops::Deref;
|
||||||
|
use thaw_utils::{class_list, mount_style};
|
||||||
|
|
||||||
|
#[component]
|
||||||
|
pub fn Tab(
|
||||||
|
#[prop(optional, into)] class: MaybeProp<String>,
|
||||||
|
#[prop(into)] value: String,
|
||||||
|
children: Children,
|
||||||
|
) -> impl IntoView {
|
||||||
|
mount_style("tab", include_str!("./tab.css"));
|
||||||
|
|
||||||
|
let tab_ref = NodeRef::<html::Button>::new();
|
||||||
|
let tab_list = TabListInjection::use_();
|
||||||
|
let value = StoredValue::new(value);
|
||||||
|
tab_list.register(TabRegisterData {
|
||||||
|
value: value.get_value(),
|
||||||
|
tab_ref,
|
||||||
|
});
|
||||||
|
on_cleanup(move || {
|
||||||
|
value.with_value(|v| tab_list.unregister(v));
|
||||||
|
});
|
||||||
|
|
||||||
|
let selected = Memo::new(move |_| {
|
||||||
|
tab_list
|
||||||
|
.selected_value
|
||||||
|
.with(|selected_value| value.with_value(|value| value == selected_value))
|
||||||
|
});
|
||||||
|
|
||||||
|
let on_select = move |_| {
|
||||||
|
tab_list.registered_tabs.with_untracked(|registered_tabs| {
|
||||||
|
if let Some(previous_selected_tab) = tab_list
|
||||||
|
.selected_value
|
||||||
|
.with_untracked(|selected_value| registered_tabs.get(selected_value))
|
||||||
|
{
|
||||||
|
let tab_el = tab_ref.get_untracked().unwrap();
|
||||||
|
let selected_tab_rect = tab_el.get_bounding_client_rect();
|
||||||
|
let previous_selected_tab_rect = previous_selected_tab
|
||||||
|
.tab_ref
|
||||||
|
.get_untracked()
|
||||||
|
.unwrap()
|
||||||
|
.get_bounding_client_rect();
|
||||||
|
|
||||||
|
let offset = previous_selected_tab_rect.x() - selected_tab_rect.x();
|
||||||
|
let scale = previous_selected_tab_rect.width() / selected_tab_rect.width();
|
||||||
|
|
||||||
|
let style = tab_el.deref().style();
|
||||||
|
let _ =
|
||||||
|
style.set_property("--thaw-tab__indicator--offset", &format!("{offset:.0}px"));
|
||||||
|
let _ = style.set_property("--thaw-tab__indicator--scale", &format!("{scale:.2}"));
|
||||||
|
|
||||||
|
request_animation_frame(move || {
|
||||||
|
let _ = style.set_property("--thaw-tab__indicator--offset", "0px");
|
||||||
|
let _ = style.set_property("--thaw-tab__indicator--scale", "1");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
tab_list.on_select(value.get_value());
|
||||||
|
};
|
||||||
|
|
||||||
|
view! {
|
||||||
|
<button
|
||||||
|
class=class_list![
|
||||||
|
"thaw-tab", ("thaw-tab--selected", move || selected.get()), class
|
||||||
|
]
|
||||||
|
role="tab"
|
||||||
|
aria-selected=move || if selected.get() { "true" } else { "false" }
|
||||||
|
ref=tab_ref
|
||||||
|
on:click=on_select
|
||||||
|
>
|
||||||
|
<span class="thaw-tab__content">
|
||||||
|
{children()}
|
||||||
|
</span>
|
||||||
|
</button>
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,83 +0,0 @@
|
||||||
use super::{TabListInjection, TabRegisterData};
|
|
||||||
use leptos::*;
|
|
||||||
use std::ops::Deref;
|
|
||||||
use thaw_utils::{class_list, mount_style};
|
|
||||||
|
|
||||||
#[component]
|
|
||||||
pub fn Tab(
|
|
||||||
#[prop(optional, into)] class: MaybeProp<String>,
|
|
||||||
#[prop(into)] value: String,
|
|
||||||
children: Children,
|
|
||||||
) -> impl IntoView {
|
|
||||||
mount_style("tab", include_str!("./tab.css"));
|
|
||||||
|
|
||||||
let tab_ref = NodeRef::<html::Button>::new();
|
|
||||||
let tab_list = TabListInjection::use_();
|
|
||||||
let value = StoredValue::new(value);
|
|
||||||
tab_list.register(TabRegisterData {
|
|
||||||
value: value.get_value(),
|
|
||||||
tab_ref,
|
|
||||||
});
|
|
||||||
on_cleanup(move || {
|
|
||||||
value.with_value(|v| tab_list.unregister(v));
|
|
||||||
});
|
|
||||||
|
|
||||||
let selected = Memo::new(move |_| {
|
|
||||||
tab_list
|
|
||||||
.selected_value
|
|
||||||
.with(|selected_value| value.with_value(|value| value == selected_value))
|
|
||||||
});
|
|
||||||
|
|
||||||
Effect::new(move |_| {
|
|
||||||
let selected = selected.get();
|
|
||||||
if selected {
|
|
||||||
tab_list.registered_tabs.with_untracked(|registered_tabs| {
|
|
||||||
if let Some(previous_selected_tab) = tab_list
|
|
||||||
.previous_selected_value
|
|
||||||
.with_value(|selected_value| registered_tabs.get(selected_value))
|
|
||||||
{
|
|
||||||
let tab_el = tab_ref.get_untracked().unwrap();
|
|
||||||
let selected_tab_rect = tab_el.get_bounding_client_rect();
|
|
||||||
let previous_selected_tab_rect = previous_selected_tab
|
|
||||||
.tab_ref
|
|
||||||
.get_untracked()
|
|
||||||
.unwrap()
|
|
||||||
.get_bounding_client_rect();
|
|
||||||
|
|
||||||
let offset = previous_selected_tab_rect.x() - selected_tab_rect.x();
|
|
||||||
let scale = previous_selected_tab_rect.width() / selected_tab_rect.width();
|
|
||||||
|
|
||||||
let style = tab_el.deref().style();
|
|
||||||
let _ = style
|
|
||||||
.set_property("--thaw-tab__indicator--offset", &format!("{offset:.0}px"));
|
|
||||||
let _ =
|
|
||||||
style.set_property("--thaw-tab__indicator--scale", &format!("{scale:.2}"));
|
|
||||||
|
|
||||||
// let _ = style.get_property_value("offsetWidth");
|
|
||||||
|
|
||||||
// let _ = style.set_property("--thaw-tab__indicator--offset", "0px");
|
|
||||||
// let _ = style.set_property("--thaw-tab__indicator--scale", "1");
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
selected
|
|
||||||
});
|
|
||||||
|
|
||||||
view! {
|
|
||||||
<button
|
|
||||||
class=class_list![
|
|
||||||
"thaw-tab", ("thaw-tab--selected", move || selected.get()), class
|
|
||||||
]
|
|
||||||
role="tab"
|
|
||||||
aria-selected=move || if selected.get() { "true" } else { "false" }
|
|
||||||
ref=tab_ref
|
|
||||||
style="--thaw-tab__indicator--offset: 0px; --thaw-tab__indicator--scale: 1"
|
|
||||||
on:click=move |_| tab_list.on_select(value.get_value())
|
|
||||||
>
|
|
||||||
<span class="thaw-tab__content">
|
|
||||||
{children()}
|
|
||||||
</span>
|
|
||||||
</button>
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -57,6 +57,7 @@ pub struct CommonTheme {
|
||||||
pub spacing_horizontal_m_nudge: String,
|
pub spacing_horizontal_m_nudge: String,
|
||||||
pub spacing_horizontal_m: String,
|
pub spacing_horizontal_m: String,
|
||||||
pub spacing_horizontal_l: String,
|
pub spacing_horizontal_l: String,
|
||||||
|
pub spacing_vertical_none: String,
|
||||||
pub spacing_vertical_s: String,
|
pub spacing_vertical_s: String,
|
||||||
pub spacing_vertical_m_nudge: String,
|
pub spacing_vertical_m_nudge: String,
|
||||||
pub spacing_vertical_m: String,
|
pub spacing_vertical_m: String,
|
||||||
|
@ -137,6 +138,7 @@ impl CommonTheme {
|
||||||
spacing_horizontal_m_nudge: "10px".into(),
|
spacing_horizontal_m_nudge: "10px".into(),
|
||||||
spacing_horizontal_m: "12px".into(),
|
spacing_horizontal_m: "12px".into(),
|
||||||
spacing_horizontal_l: "16px".into(),
|
spacing_horizontal_l: "16px".into(),
|
||||||
|
spacing_vertical_none: "0".into(),
|
||||||
spacing_vertical_s: "8px".into(),
|
spacing_vertical_s: "8px".into(),
|
||||||
spacing_vertical_m_nudge: "10px".into(),
|
spacing_vertical_m_nudge: "10px".into(),
|
||||||
spacing_vertical_m: "12px".into(),
|
spacing_vertical_m: "12px".into(),
|
||||||
|
|
Loading…
Add table
Reference in a new issue