freya_components/
sidebar.rs1use dioxus::prelude::*;
2use freya_core::platform::CursorIcon;
3use freya_elements as dioxus_elements;
4use freya_hooks::{
5 use_activable_route,
6 use_applied_theme,
7 use_platform,
8 SidebarItemTheme,
9 SidebarItemThemeWith,
10 SidebarTheme,
11 SidebarThemeWith,
12};
13
14use crate::{
15 ButtonStatus,
16 ScrollView,
17};
18
19#[allow(non_snake_case)]
20#[component]
21pub fn Sidebar(
22 theme: Option<SidebarThemeWith>,
24 children: Element,
26 sidebar: Element,
28 #[props(default = "180".to_string())]
30 width: String,
31) -> Element {
32 let SidebarTheme {
33 spacing,
34 font_theme,
35 background,
36 } = use_applied_theme!(&theme, sidebar);
37
38 rsx!(
39 rect {
40 width: "100%",
41 height: "100%",
42 direction: "horizontal",
43 rect {
44 overflow: "clip",
45 width,
46 height: "100%",
47 background: "{background}",
48 color: "{font_theme.color}",
49 shadow: "2 0 5 0 rgb(0, 0, 0, 30)",
50 ScrollView {
51 padding: "8",
52 spacing,
53 {sidebar}
54 }
55 }
56 rect {
57 overflow: "clip",
58 width: "fill",
59 height: "100%",
60 color: "{font_theme.color}",
61 {children}
62 }
63 }
64 )
65}
66
67#[allow(non_snake_case)]
68#[component]
69pub fn SidebarItem(
70 theme: Option<SidebarItemThemeWith>,
72 children: Element,
74 onpress: Option<EventHandler<()>>,
76) -> Element {
77 let SidebarItemTheme {
78 margin,
79 hover_background,
80 background,
81 font_theme,
82 } = use_applied_theme!(&theme, sidebar_item);
83 let mut status = use_signal(ButtonStatus::default);
84 let platform = use_platform();
85 let is_active = use_activable_route();
86
87 use_drop(move || {
88 if *status.read() == ButtonStatus::Hovering {
89 platform.set_cursor(CursorIcon::default());
90 }
91 });
92
93 let onclick = move |_| {
94 if let Some(onpress) = &onpress {
95 onpress.call(());
96 }
97 };
98
99 let onmouseenter = move |_| {
100 platform.set_cursor(CursorIcon::Pointer);
101 status.set(ButtonStatus::Hovering);
102 };
103
104 let onmouseleave = move |_| {
105 platform.set_cursor(CursorIcon::default());
106 status.set(ButtonStatus::default());
107 };
108
109 let background = match *status.read() {
110 _ if is_active => hover_background,
111 ButtonStatus::Hovering => hover_background,
112 ButtonStatus::Idle => background,
113 };
114
115 rsx!(
116 rect {
117 overflow: "clip",
118 margin: "{margin}",
119 onclick,
120 onmouseenter,
121 onmouseleave,
122 width: "100%",
123 height: "auto",
124 color: "{font_theme.color}",
125 corner_radius: "99",
126 padding: "8 10",
127 background: "{background}",
128 {children}
129 }
130 )
131}