yew_nav_link/
nav_link.rs

1// Import necessary modules from Yew and Yew Router
2use std::marker::PhantomData;
3
4use yew::prelude::*;
5use yew_router::prelude::*;
6
7/// Props for NavLink component.
8/// R: Routable - A trait bound to ensure that this component can only be used
9/// with routable types.
10#[derive(Properties, PartialEq)]
11pub struct NavLinkProps<R: Routable + PartialEq + Clone + 'static> {
12    /// The destination route for the link.
13    pub to:             R,
14    /// Children of this component (usually text or other elements to be
15    /// rendered within the link).
16    pub children:       Children,
17    /// Marker for the generic type R. It does not hold any value.
18    #[prop_or_default]
19    pub(crate) _marker: PhantomData<R>
20}
21
22/// NavLink component for Yew applications using Yew Router.
23///
24/// This component creates a navigational link that is aware of its active
25/// state, based on the current route in the application.
26///
27/// The component is generic over `R`, where `R` must implement the `Routable`
28/// trait. This allows the NavLink to be used with any set of routable types.
29///
30/// # Example
31///
32/// ```rust
33/// use yew::prelude::*;
34/// use yew_nav_link::NavLink;
35/// use yew_router::prelude::*;
36///
37/// #[derive(Clone, PartialEq, Debug, Routable)]
38/// enum AppRoute {
39///     #[at("/")]
40///     Home,
41///     #[at("/about")]
42///     About
43/// }
44///
45/// #[function_component(App)]
46/// pub fn app() -> Html {
47///     html! {
48///         <nav>
49///             <NavLink<AppRoute> to={AppRoute::Home}>{ "Home" }</NavLink<AppRoute>>
50///             <NavLink<AppRoute> to={AppRoute::About}>{ "About" }</NavLink<AppRoute>>
51///             // ... other NavLinks
52///         </nav>
53///     }
54/// }
55/// ```
56#[function_component(NavLink)]
57pub fn nav_link<R: Routable + PartialEq + Clone + 'static>(props: &NavLinkProps<R>) -> Html {
58    // use_route hook is used to get the current route of the application.
59    let current_route = use_route::<R>();
60
61    // Determine if the NavLink's route matches the current route.
62    // If they match, the link is considered 'active'.
63    let is_active = if let Some(route) = current_route {
64        route == props.to
65    } else {
66        false
67    };
68
69    // CSS class for the NavLink.
70    // The 'active' class is conditionally added based on the active state.
71    let class = format!("nav-link {}", if is_active { "active" } else { "" });
72
73    // Render the NavLink using the Yew's Link component.
74    // The Link component is responsible for handling the navigation.
75    html! {
76        <Link<R> to={props.to.clone()} classes={classes!(class)}>
77            // Rendering children elements passed to the NavLink.
78            { for props.children.iter() }
79        </Link<R>>
80    }
81}
82
83/// Creates a NavLink component for the specified route with the provided
84/// children.
85///
86/// This function creates a NavLink component for Yew applications using Yew
87/// Router. It takes a route (`R`) and children text, and returns a NavLink
88/// component.
89///
90/// # Arguments
91///
92/// * `to` - The destination route for the link.
93/// * `children` - The text or other elements to be rendered within the link.
94///
95/// # Example
96///
97/// ```rust
98/// use yew::prelude::*;
99/// use yew_nav_link::{NavLink, nav_link};
100/// use yew_router::prelude::*;
101///
102/// #[derive(Clone, PartialEq, Debug, Routable)]
103/// enum HomeRoute {
104///     #[at("/")]
105///     IntroPage,
106///     #[at("/about")]
107///     About
108/// }
109///
110/// #[function_component(Menu)]
111/// fn menu() -> Html {
112///     html! {
113///         <ul class="nav">
114///             // Creating a NavLink for the Home route with the text "Home Page"
115///             <li class="nav-item">
116///                 { nav_link(HomeRoute::IntroPage, "Home Page") }
117///             </li>
118///             <li class="nav-item">
119///                 { nav_link(HomeRoute::About, "About") }
120///             </li>
121///         </ul>
122///     }
123/// }
124/// ```
125///
126/// # Generic Type
127///
128/// * `R` - The route type that implements the `Routable` trait.
129///
130/// # Returns
131///
132/// An HTML representation of the NavLink component.
133///
134/// # Note
135///
136/// The `to` parameter must be of a type that implements the `Routable` trait.
137pub fn nav_link<R: Routable + PartialEq + Clone + 'static>(to: R, children: &str) -> Html {
138    html! {
139        <NavLink<R> to={to}>{ children }</NavLink<R>>
140    }
141}