freya_components/activable_route.rs
1use dioxus::prelude::*;
2use dioxus_router::{
3 hooks::use_route,
4 prelude::Routable,
5};
6use freya_hooks::ActivableRouteContext;
7
8/// Sometimes you might want to know if a route is selected so you can style a specific UI element in a different way,
9/// like a button with a different color.
10/// To avoid cluttering your components with router-specific code you might instead want to wrap your component in an `ActivableRoute`
11/// and inside your component call `use_activable_route`.
12///
13/// This way, your component and all its desdendants will just know whether a route is activated or not, but not which one.
14///
15/// ```rs
16/// Link {
17/// to: Route::Home, // Direction route
18/// ActivableRoute {
19/// route: Route::Home, // Activation route
20/// SidebarItem {
21/// // `SidebarItem` will now appear "activated" when the route is `Route::Home`
22/// // `ActivableRoute` is letting it know whether `Route::Home` is enabled
23/// // or not, without the need to add router-specific logic in `SidebarItem`.
24/// label {
25/// "Go to Hey ! 👋"
26/// }
27/// },
28/// }
29/// }
30/// ```
31#[allow(non_snake_case)]
32#[component]
33pub fn ActivableRoute<T: Clone + PartialEq + Routable + 'static>(
34 children: Element,
35 route: T,
36 #[props(default = Vec::new())] routes: Vec<T>,
37 #[props(default = false)] exact: bool,
38) -> Element {
39 let current_route = use_route::<T>();
40
41 let is_descendent_route_active = current_route.is_child_of(&route);
42 let is_descendent_routes_active = routes.iter().any(|route| current_route.is_child_of(route));
43 let is_descendent_active =
44 !exact && (is_descendent_route_active || is_descendent_routes_active);
45
46 let is_exact_active = current_route == route || routes.contains(¤t_route);
47
48 let is_active = is_descendent_active || is_exact_active;
49
50 let mut ctx = use_context_provider::<ActivableRouteContext>(|| {
51 ActivableRouteContext(Signal::new(is_active))
52 });
53
54 if *ctx.0.peek() != is_active {
55 *ctx.0.write() = is_active;
56 }
57
58 rsx!({ children })
59}