mirror of
https://github.com/adoyle0/thaw.git
synced 2025-02-02 08:34:15 -05:00
fix: NavDrawer selected category value error (#252)
This commit is contained in:
parent
583b03100e
commit
f9d39f740c
5 changed files with 46 additions and 63 deletions
|
@ -53,7 +53,7 @@ view! {
|
||||||
| --- | --- | --- | --- |
|
| --- | --- | --- | --- |
|
||||||
| class | `MaybeProp<String>,` | `Default::default()` | |
|
| class | `MaybeProp<String>,` | `Default::default()` | |
|
||||||
| selected_value | `OptionModel<String>` | `Default::default()` | The value of the currently selected navItem. |
|
| selected_value | `OptionModel<String>` | `Default::default()` | The value of the currently selected navItem. |
|
||||||
| selected_category_value | `VecModel<String>` | `vec![]` | Indicates a category that has a selected child Will show the category as selected if it is closed. |
|
| selected_category_value | `OptionModel<String>` | `None` | Indicates a category that has a selected child Will show the category as selected if it is closed. |
|
||||||
| nav_drawer_header | slot `Option<NavDrawerHeader>` | `None` | |
|
| nav_drawer_header | slot `Option<NavDrawerHeader>` | `None` | |
|
||||||
| nav_drawer_footer | slot `Option<NavDrawerFooter>` | `None` | |
|
| nav_drawer_footer | slot `Option<NavDrawerFooter>` | `None` | |
|
||||||
| children | `Children` | | |
|
| children | `Children` | | |
|
||||||
|
|
|
@ -69,7 +69,8 @@
|
||||||
background-color: var(--colorNeutralBackground4Pressed);
|
background-color: var(--colorNeutralBackground4Pressed);
|
||||||
}
|
}
|
||||||
|
|
||||||
.thaw-nav-item--selected::after {
|
.thaw-nav-item--selected::after,
|
||||||
|
.thaw-nav-category-item--selected[aria-expanded="false"]::after {
|
||||||
content: "";
|
content: "";
|
||||||
position: absolute;
|
position: absolute;
|
||||||
width: 4px;
|
width: 4px;
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
use super::NavDrawerInjection;
|
use super::NavDrawerInjection;
|
||||||
use crate::Icon;
|
use crate::Icon;
|
||||||
use leptos::{either::Either, html, prelude::*};
|
use leptos::{context::Provider, either::Either, html, prelude::*};
|
||||||
use thaw_components::CSSTransition;
|
use thaw_components::CSSTransition;
|
||||||
use thaw_utils::{class_list, StoredMaybeSignal, VecModelWithValue};
|
use thaw_utils::{class_list, StoredMaybeSignal};
|
||||||
|
|
||||||
#[component]
|
#[component]
|
||||||
pub fn NavCategory(
|
pub fn NavCategory(
|
||||||
|
@ -13,56 +13,9 @@ pub fn NavCategory(
|
||||||
let nav_drawer = NavDrawerInjection::expect_context();
|
let nav_drawer = NavDrawerInjection::expect_context();
|
||||||
let value: StoredMaybeSignal<_> = value.into();
|
let value: StoredMaybeSignal<_> = value.into();
|
||||||
let group_ref = NodeRef::<html::Div>::new();
|
let group_ref = NodeRef::<html::Div>::new();
|
||||||
let is_show_group = Memo::new(move |_| {
|
let is_show_group = RwSignal::new(false);
|
||||||
nav_drawer
|
let is_selected_category =
|
||||||
.selected_category_value
|
Memo::new(move |_| value.with(|value| nav_drawer.is_selected_category(value)));
|
||||||
.with(|selected_category_value| {
|
|
||||||
value.with(|value| match selected_category_value {
|
|
||||||
VecModelWithValue::T(v) => v == value,
|
|
||||||
VecModelWithValue::Option(v) => v.as_ref() == Some(value),
|
|
||||||
VecModelWithValue::Vec(v) => v.contains(value),
|
|
||||||
})
|
|
||||||
})
|
|
||||||
});
|
|
||||||
|
|
||||||
let on_click = move |_| {
|
|
||||||
let value = value.get_untracked();
|
|
||||||
let is_show_group = is_show_group.get_untracked();
|
|
||||||
nav_drawer
|
|
||||||
.selected_category_value
|
|
||||||
.update(|selected_category_value| {
|
|
||||||
match selected_category_value {
|
|
||||||
(None, None, Some(v)) => {
|
|
||||||
if is_show_group {
|
|
||||||
if let Some(index) = v.iter().position(|item| item == &value) {
|
|
||||||
v.remove(index);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
v.push(value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
(None, Some(v), None) => {
|
|
||||||
if is_show_group {
|
|
||||||
*v = None;
|
|
||||||
} else {
|
|
||||||
*v = Some(value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
(Some(v), None, None) => {
|
|
||||||
if is_show_group {
|
|
||||||
v.clear();
|
|
||||||
} else {
|
|
||||||
*v = value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => unreachable!(),
|
|
||||||
}
|
|
||||||
|
|
||||||
if is_show_group {
|
|
||||||
} else {
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
let NavCategoryItem {
|
let NavCategoryItem {
|
||||||
class: item_class,
|
class: item_class,
|
||||||
|
@ -72,9 +25,13 @@ pub fn NavCategory(
|
||||||
|
|
||||||
view! {
|
view! {
|
||||||
<button
|
<button
|
||||||
class=class_list!["thaw-nav-category-item", item_class]
|
class=class_list![
|
||||||
on:click=on_click
|
"thaw-nav-category-item",
|
||||||
aria-expanded=move || is_show_group.get()
|
("thaw-nav-category-item--selected", move || is_selected_category.get()),
|
||||||
|
item_class
|
||||||
|
]
|
||||||
|
on:click=move |_| { is_show_group.update(|show| *show = !*show); }
|
||||||
|
aria-expanded=move || if is_show_group.get() { "true" } else { "false" }
|
||||||
>
|
>
|
||||||
{move || {
|
{move || {
|
||||||
if let Some(icon) = item_icon.get() {
|
if let Some(icon) = item_icon.get() {
|
||||||
|
@ -117,7 +74,9 @@ pub fn NavCategory(
|
||||||
node_ref=group_ref
|
node_ref=group_ref
|
||||||
style=move || display.get().unwrap_or_default()
|
style=move || display.get().unwrap_or_default()
|
||||||
>
|
>
|
||||||
|
<Provider value=NavCategoryInjection { value }>
|
||||||
{children()}
|
{children()}
|
||||||
|
</Provider>
|
||||||
</div>
|
</div>
|
||||||
</CSSTransition>
|
</CSSTransition>
|
||||||
}
|
}
|
||||||
|
@ -131,3 +90,14 @@ pub struct NavCategoryItem {
|
||||||
icon: MaybeProp<icondata_core::Icon>,
|
icon: MaybeProp<icondata_core::Icon>,
|
||||||
children: Children,
|
children: Children,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Copy)]
|
||||||
|
pub(crate) struct NavCategoryInjection {
|
||||||
|
pub value: StoredMaybeSignal<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl NavCategoryInjection {
|
||||||
|
pub fn use_context() -> Option<Self> {
|
||||||
|
use_context()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
use crate::Scrollbar;
|
use crate::Scrollbar;
|
||||||
use leptos::{context::Provider, prelude::*};
|
use leptos::{context::Provider, prelude::*};
|
||||||
use thaw_components::OptionComp;
|
use thaw_components::OptionComp;
|
||||||
use thaw_utils::{class_list, mount_style, OptionModel, VecModel};
|
use thaw_utils::{class_list, mount_style, OptionModel, OptionModelWithValue};
|
||||||
|
|
||||||
#[component]
|
#[component]
|
||||||
pub fn NavDrawer(
|
pub fn NavDrawer(
|
||||||
|
@ -10,8 +10,8 @@ pub fn NavDrawer(
|
||||||
#[prop(optional, into)]
|
#[prop(optional, into)]
|
||||||
selected_value: OptionModel<String>,
|
selected_value: OptionModel<String>,
|
||||||
/// Indicates a category that has a selected child Will show the category as selected if it is closed.
|
/// Indicates a category that has a selected child Will show the category as selected if it is closed.
|
||||||
#[prop(default = vec![].into(), into)]
|
#[prop(optional, into)]
|
||||||
selected_category_value: VecModel<String>,
|
selected_category_value: OptionModel<String>,
|
||||||
children: Children,
|
children: Children,
|
||||||
#[prop(optional)] nav_drawer_header: Option<NavDrawerHeader>,
|
#[prop(optional)] nav_drawer_header: Option<NavDrawerHeader>,
|
||||||
#[prop(optional)] nav_drawer_footer: Option<NavDrawerFooter>,
|
#[prop(optional)] nav_drawer_footer: Option<NavDrawerFooter>,
|
||||||
|
@ -51,11 +51,19 @@ pub struct NavDrawerFooter {
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub(crate) struct NavDrawerInjection {
|
pub(crate) struct NavDrawerInjection {
|
||||||
pub selected_value: OptionModel<String>,
|
pub selected_value: OptionModel<String>,
|
||||||
pub selected_category_value: VecModel<String>,
|
pub selected_category_value: OptionModel<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl NavDrawerInjection {
|
impl NavDrawerInjection {
|
||||||
pub fn expect_context() -> Self {
|
pub fn expect_context() -> Self {
|
||||||
expect_context()
|
expect_context()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn is_selected_category(&self, value: &String) -> bool {
|
||||||
|
self.selected_category_value
|
||||||
|
.with(|selected_category_value| match selected_category_value {
|
||||||
|
OptionModelWithValue::T(v) => v == value,
|
||||||
|
OptionModelWithValue::Option(v) => v.as_ref() == Some(value),
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use super::NavDrawerInjection;
|
use super::{NavCategoryInjection, NavDrawerInjection};
|
||||||
use crate::Icon;
|
use crate::Icon;
|
||||||
use leptos::{either::Either, prelude::*};
|
use leptos::{either::Either, prelude::*};
|
||||||
use thaw_utils::{class_list, OptionModelWithValue, StoredMaybeSignal};
|
use thaw_utils::{class_list, OptionModelWithValue, StoredMaybeSignal};
|
||||||
|
@ -12,6 +12,7 @@ pub fn NavItem(
|
||||||
children: Children,
|
children: Children,
|
||||||
) -> impl IntoView {
|
) -> impl IntoView {
|
||||||
let nav_drawer = NavDrawerInjection::expect_context();
|
let nav_drawer = NavDrawerInjection::expect_context();
|
||||||
|
let nav_category = NavCategoryInjection::use_context();
|
||||||
let value: StoredMaybeSignal<_> = value.into();
|
let value: StoredMaybeSignal<_> = value.into();
|
||||||
let on_click = move |_| {
|
let on_click = move |_| {
|
||||||
let value = value.get_untracked();
|
let value = value.get_untracked();
|
||||||
|
@ -23,6 +24,9 @@ pub fn NavItem(
|
||||||
})
|
})
|
||||||
{
|
{
|
||||||
nav_drawer.selected_value.set(Some(value));
|
nav_drawer.selected_value.set(Some(value));
|
||||||
|
nav_drawer
|
||||||
|
.selected_category_value
|
||||||
|
.set(nav_category.map(|c| c.value.get_untracked()));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue