freya_components/
sidebar.rs1use freya_core::prelude::*;
2use torin::size::Size;
3
4use crate::{
5 activable_route_context::use_activable_route,
6 get_theme,
7 scrollviews::ScrollView,
8 theming::component_themes::{
9 SideBarItemTheme,
10 SideBarItemThemePartial,
11 SideBarTheme,
12 SideBarThemePartial,
13 },
14};
15
16#[derive(PartialEq)]
17pub struct SideBar {
18 pub(crate) theme: Option<SideBarThemePartial>,
20 content: Option<Element>,
22 bar: Option<Element>,
24 width: Size,
26}
27
28impl Default for SideBar {
29 fn default() -> Self {
30 Self::new()
31 }
32}
33
34impl SideBar {
35 pub fn new() -> Self {
36 Self {
37 theme: None,
38 content: None,
39 bar: None,
40 width: Size::px(180.),
41 }
42 }
43
44 pub fn content(mut self, content: impl Into<Element>) -> Self {
45 self.content = Some(content.into());
46 self
47 }
48
49 pub fn bar(mut self, bar: impl Into<Element>) -> Self {
50 self.bar = Some(bar.into());
51 self
52 }
53
54 pub fn width(mut self, width: impl Into<Size>) -> Self {
55 self.width = width.into();
56 self
57 }
58}
59
60impl Render for SideBar {
61 fn render(&self) -> impl IntoElement {
62 let SideBarTheme {
63 spacing,
64 padding,
65 background,
66 color,
67 } = get_theme!(&self.theme, sidebar);
68
69 rect()
70 .horizontal()
71 .width(Size::fill())
72 .height(Size::fill())
73 .color(color)
74 .child(
75 rect()
76 .overflow(Overflow::Clip)
77 .width(self.width.clone())
78 .height(Size::fill())
79 .background(background)
80 .child(
81 ScrollView::new()
82 .width(self.width.clone())
83 .spacing(spacing)
84 .child(rect().padding(padding).maybe_child(self.bar.clone())),
85 ),
86 )
87 .child(
88 rect()
89 .overflow(Overflow::Clip)
90 .expanded()
91 .maybe_child(self.content.clone()),
92 )
93 }
94}
95
96#[derive(Debug, Default, PartialEq, Clone, Copy)]
97pub enum ButtonStatus {
98 #[default]
100 Idle,
101 Hovering,
103}
104#[derive(PartialEq)]
105pub struct SideBarItem {
106 pub(crate) theme: Option<SideBarItemThemePartial>,
108 children: Vec<Element>,
110 on_press: Option<EventHandler<Event<PressEventData>>>,
112 overflow: Overflow,
114 key: DiffKey,
115}
116
117impl KeyExt for SideBarItem {
118 fn write_key(&mut self) -> &mut DiffKey {
119 &mut self.key
120 }
121}
122
123impl Default for SideBarItem {
124 fn default() -> Self {
125 Self::new()
126 }
127}
128
129impl ChildrenExt for SideBarItem {
130 fn get_children(&mut self) -> &mut Vec<Element> {
131 &mut self.children
132 }
133}
134
135impl SideBarItem {
136 pub fn new() -> Self {
137 Self {
138 theme: None,
139 children: Vec::new(),
140 on_press: None,
141 overflow: Overflow::Clip,
142 key: DiffKey::None,
143 }
144 }
145
146 pub fn on_press(mut self, on_press: impl Into<EventHandler<Event<PressEventData>>>) -> Self {
147 self.on_press = Some(on_press.into());
148 self
149 }
150
151 pub fn overflow(mut self, overflow: impl Into<Overflow>) -> Self {
152 self.overflow = overflow.into();
153 self
154 }
155}
156
157impl Render for SideBarItem {
158 fn render(&self) -> impl IntoElement {
159 let SideBarItemTheme {
160 margin,
161 hover_background,
162 background,
163 corner_radius,
164 padding,
165 color,
166 } = get_theme!(&self.theme, sidebar_item);
167 let mut status = use_state(ButtonStatus::default);
168 let is_active = use_activable_route();
169
170 let on_pointer_enter = move |_| {
171 status.set(ButtonStatus::Hovering);
172 };
173
174 let on_pointer_leave = move |_| {
175 status.set(ButtonStatus::default());
176 };
177
178 let background = match *status.read() {
179 _ if is_active => hover_background,
180 ButtonStatus::Hovering => hover_background,
181 ButtonStatus::Idle => background,
182 };
183
184 rect()
186 .map(self.on_press.clone(), |rect, on_press| {
187 rect.on_press(on_press)
188 })
189 .on_pointer_enter(on_pointer_enter)
190 .on_pointer_leave(on_pointer_leave)
191 .overflow(self.overflow)
192 .width(Size::fill())
193 .margin(margin)
194 .padding(padding)
195 .color(color)
196 .background(background)
197 .corner_radius(corner_radius)
198 .children(self.children.clone())
199 }
200
201 fn render_key(&self) -> DiffKey {
202 self.key.clone().or(self.default_key())
203 }
204}