mirror of
https://github.com/adoyle0/thaw.git
synced 2025-03-11 13:32:54 -04:00
feat: tab select
This commit is contained in:
parent
c7da724cdc
commit
938342ab1f
4 changed files with 84 additions and 16 deletions
|
@ -8,26 +8,19 @@ use thaw_utils::{class_list, mount_style, Model};
|
||||||
|
|
||||||
#[component]
|
#[component]
|
||||||
pub fn TabList(
|
pub fn TabList(
|
||||||
#[prop(optional, into)] selected_value: Model<String>,
|
|
||||||
#[prop(optional, into)] class: MaybeProp<String>,
|
#[prop(optional, into)] class: MaybeProp<String>,
|
||||||
|
/// The value of the currently selected tab.
|
||||||
|
#[prop(optional, into)]
|
||||||
|
selected_value: Model<String>,
|
||||||
children: Children,
|
children: Children,
|
||||||
) -> impl IntoView {
|
) -> impl IntoView {
|
||||||
mount_style("tab-list", include_str!("./tab-list.css"));
|
mount_style("tab-list", include_str!("./tab-list.css"));
|
||||||
|
|
||||||
let registered_tabs = RwSignal::new(HashMap::new());
|
let registered_tabs = RwSignal::new(HashMap::new());
|
||||||
// request_animation_frame(move || {
|
|
||||||
// let list_rect = label_list.get_bounding_client_rect();
|
|
||||||
// let rect = label.get_bounding_client_rect();
|
|
||||||
// label_line
|
|
||||||
// .set(
|
|
||||||
// Some(TabsLabelLine {
|
|
||||||
// width: rect.width(),
|
|
||||||
// left: rect.left() - list_rect.left(),
|
|
||||||
// }),
|
|
||||||
// );
|
|
||||||
// });
|
|
||||||
view! {
|
view! {
|
||||||
<Provider value=TabListInjection {
|
<Provider value=TabListInjection {
|
||||||
|
previous_selected_value: StoredValue::new(selected_value.get_untracked()),
|
||||||
selected_value,
|
selected_value,
|
||||||
registered_tabs,
|
registered_tabs,
|
||||||
}>
|
}>
|
||||||
|
@ -43,8 +36,9 @@ pub fn TabList(
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub(crate) struct TabListInjection {
|
pub(crate) struct TabListInjection {
|
||||||
|
pub previous_selected_value: StoredValue<String>,
|
||||||
pub selected_value: Model<String>,
|
pub selected_value: Model<String>,
|
||||||
registered_tabs: RwSignal<HashMap<String, TabRegisterData>>,
|
pub registered_tabs: RwSignal<HashMap<String, TabRegisterData>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Copy for TabListInjection {}
|
impl Copy for TabListInjection {}
|
||||||
|
@ -65,9 +59,15 @@ impl TabListInjection {
|
||||||
map.remove(value);
|
map.remove(value);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn on_select(&self, value: String) {
|
||||||
|
self.previous_selected_value
|
||||||
|
.set_value(self.selected_value.get_untracked());
|
||||||
|
self.selected_value.set(value);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) struct TabRegisterData {
|
pub(crate) struct TabRegisterData {
|
||||||
value: String,
|
pub value: String,
|
||||||
tab_ref: NodeRef<html::Button>,
|
pub tab_ref: NodeRef<html::Button>,
|
||||||
}
|
}
|
||||||
|
|
|
@ -59,3 +59,28 @@
|
||||||
.thaw-tab:active .thaw-tab__content {
|
.thaw-tab:active .thaw-tab__content {
|
||||||
color: var(--colorNeutralForeground2Pressed);
|
color: var(--colorNeutralForeground2Pressed);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.thaw-tab--selected {
|
||||||
|
overflow: visible;
|
||||||
|
}
|
||||||
|
|
||||||
|
.thaw-tab--selected .thaw-tab__content {
|
||||||
|
font-weight: var(--fontWeightSemibold);
|
||||||
|
}
|
||||||
|
|
||||||
|
.thaw-tab--selected::after {
|
||||||
|
position: absolute;
|
||||||
|
content: "";
|
||||||
|
transform: translateX(var(--thaw-tab__indicator--offset))
|
||||||
|
scaleX(var(--thaw-tab__indicator--scale));
|
||||||
|
transform-origin: left center;
|
||||||
|
transition-timing-function: var(--curveDecelerateMax);
|
||||||
|
transition-duration: var(--durationSlow);
|
||||||
|
transition-property: transform;
|
||||||
|
right: var(--spacingHorizontalM);
|
||||||
|
left: var(--spacingHorizontalM);
|
||||||
|
height: var(--strokeWidthThicker);
|
||||||
|
bottom: 0px;
|
||||||
|
background-color: var(--colorCompoundBrandStroke);
|
||||||
|
border-radius: var(--borderRadiusCircular);
|
||||||
|
}
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
use super::{TabListInjection, TabRegisterData};
|
use super::{TabListInjection, TabRegisterData};
|
||||||
use leptos::*;
|
use leptos::*;
|
||||||
|
use std::ops::Deref;
|
||||||
use thaw_utils::{class_list, mount_style};
|
use thaw_utils::{class_list, mount_style};
|
||||||
|
|
||||||
#[component]
|
#[component]
|
||||||
|
@ -27,14 +28,52 @@ pub fn Tab(
|
||||||
.with(|selected_value| value.with_value(|value| value == 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! {
|
view! {
|
||||||
<button
|
<button
|
||||||
class=class_list![
|
class=class_list![
|
||||||
"thaw-tab", ("thaw-tab--hidden", move || selected.get()), class
|
"thaw-tab", ("thaw-tab--selected", move || selected.get()), class
|
||||||
]
|
]
|
||||||
role="tab"
|
role="tab"
|
||||||
aria-selected=move || if selected.get() { "true" } else { "false" }
|
aria-selected=move || if selected.get() { "true" } else { "false" }
|
||||||
ref=tab_ref
|
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">
|
<span class="thaw-tab__content">
|
||||||
{children()}
|
{children()}
|
||||||
|
|
|
@ -65,7 +65,9 @@ pub struct CommonTheme {
|
||||||
pub duration_ultra_fast: String,
|
pub duration_ultra_fast: String,
|
||||||
pub duration_faster: String,
|
pub duration_faster: String,
|
||||||
pub duration_normal: String,
|
pub duration_normal: String,
|
||||||
|
pub duration_slow: String,
|
||||||
pub curve_accelerate_mid: String,
|
pub curve_accelerate_mid: String,
|
||||||
|
pub curve_decelerate_max: String,
|
||||||
pub curve_decelerate_mid: String,
|
pub curve_decelerate_mid: String,
|
||||||
pub curve_easy_ease: String,
|
pub curve_easy_ease: String,
|
||||||
|
|
||||||
|
@ -143,7 +145,9 @@ impl CommonTheme {
|
||||||
duration_ultra_fast: "50ms".into(),
|
duration_ultra_fast: "50ms".into(),
|
||||||
duration_faster: "100ms".into(),
|
duration_faster: "100ms".into(),
|
||||||
duration_normal: "200ms".into(),
|
duration_normal: "200ms".into(),
|
||||||
|
duration_slow: "300ms".into(),
|
||||||
curve_accelerate_mid: "cubic-bezier(1,0,1,1)".into(),
|
curve_accelerate_mid: "cubic-bezier(1,0,1,1)".into(),
|
||||||
|
curve_decelerate_max: "cubic-bezier(0.1,0.9,0.2,1)".into(),
|
||||||
curve_decelerate_mid: "cubic-bezier(0,0,0,1)".into(),
|
curve_decelerate_mid: "cubic-bezier(0,0,0,1)".into(),
|
||||||
curve_easy_ease: "cubic-bezier(0.33,0,0.67,1)".into(),
|
curve_easy_ease: "cubic-bezier(0.33,0,0.67,1)".into(),
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue