yew_nested_router/components/
active.rs

1use crate::prelude::Target;
2use crate::router::use_router;
3use yew::prelude::*;
4
5/// Properties for [`Active`]
6#[derive(Clone, Debug, PartialEq, Properties)]
7pub struct ActiveProperties<T>
8where
9    T: Target,
10{
11    /// The target to check for
12    #[prop_or_default]
13    pub route: Option<T>,
14
15    /// Its content
16    #[prop_or_default]
17    pub children: Html,
18
19    #[prop_or_default]
20    pub id: Option<AttrValue>,
21
22    /// The HTML element to use
23    #[prop_or_else(default::element)]
24    pub element: String,
25
26    /// base classes
27    #[prop_or_default]
28    pub class: Classes,
29
30    /// additional classes when active
31    #[prop_or_default]
32    pub active: Classes,
33
34    /// additional classes when inactive
35    #[prop_or_default]
36    pub inactive: Classes,
37}
38
39mod default {
40    pub fn element() -> String {
41        "span".to_string()
42    }
43}
44
45/// A style element, allowing to add cass classes based on the target's active state.
46#[function_component(Active)]
47pub fn active<T>(props: &ActiveProperties<T>) -> Html
48where
49    T: Target,
50{
51    let router = use_router().expect("Need Router or Nested component");
52
53    let mut class = props.class.clone();
54
55    let active = match &props.route {
56        Some(route) => router.is_same(route),
57        None => router.active().is_some(),
58    };
59
60    match active {
61        true => class.extend(props.active.clone()),
62        false => class.extend(props.inactive.clone()),
63    }
64
65    html!(
66        <@{props.element.clone()}
67            {class}
68            id={props.id.clone()}
69        >
70            { props.children.clone() }
71        </@>
72    )
73}