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 theming::component_themes::{
8 SideBarItemTheme,
9 SideBarItemThemePartial,
10 },
11};
12#[derive(Debug, Default, PartialEq, Clone, Copy)]
13pub enum SideBarItemStatus {
14 #[default]
16 Idle,
17 Hovering,
19}
20
21#[derive(Clone, PartialEq)]
56pub struct SideBarItem {
57 pub(crate) theme: Option<SideBarItemThemePartial>,
59 children: Vec<Element>,
61 on_press: Option<EventHandler<Event<PressEventData>>>,
63 overflow: Overflow,
65 key: DiffKey,
66}
67
68impl KeyExt for SideBarItem {
69 fn write_key(&mut self) -> &mut DiffKey {
70 &mut self.key
71 }
72}
73
74impl Default for SideBarItem {
75 fn default() -> Self {
76 Self::new()
77 }
78}
79
80impl ChildrenExt for SideBarItem {
81 fn get_children(&mut self) -> &mut Vec<Element> {
82 &mut self.children
83 }
84}
85
86impl SideBarItem {
87 pub fn new() -> Self {
88 Self {
89 theme: None,
90 children: Vec::new(),
91 on_press: None,
92 overflow: Overflow::Clip,
93 key: DiffKey::None,
94 }
95 }
96
97 pub fn on_press(mut self, on_press: impl Into<EventHandler<Event<PressEventData>>>) -> Self {
98 self.on_press = Some(on_press.into());
99 self
100 }
101
102 pub fn overflow(mut self, overflow: impl Into<Overflow>) -> Self {
103 self.overflow = overflow.into();
104 self
105 }
106
107 pub fn get_theme(&self) -> Option<&SideBarItemThemePartial> {
109 self.theme.as_ref()
110 }
111
112 pub fn theme(mut self, theme: SideBarItemThemePartial) -> Self {
114 self.theme = Some(theme);
115 self
116 }
117}
118
119impl Component for SideBarItem {
120 fn render(&self) -> impl IntoElement {
121 let SideBarItemTheme {
122 margin,
123 hover_background,
124 active_background,
125 background,
126 corner_radius,
127 padding,
128 color,
129 } = get_theme!(&self.theme, sidebar_item);
130 let mut status = use_state(SideBarItemStatus::default);
131 let is_active = use_activable_route();
132
133 let on_pointer_enter = move |_| {
134 status.set(SideBarItemStatus::Hovering);
135 };
136
137 let on_pointer_leave = move |_| {
138 status.set(SideBarItemStatus::default());
139 };
140
141 let background = match *status.read() {
142 _ if is_active => active_background,
143 SideBarItemStatus::Hovering => hover_background,
144 SideBarItemStatus::Idle => background,
145 };
146
147 rect()
148 .a11y_focusable(true)
149 .a11y_role(AccessibilityRole::Link)
150 .map(self.on_press.clone(), |rect, on_press| {
151 rect.on_press(on_press)
152 })
153 .on_pointer_enter(on_pointer_enter)
154 .on_pointer_leave(on_pointer_leave)
155 .overflow(self.overflow)
156 .width(Size::fill())
157 .margin(margin)
158 .padding(padding)
159 .color(color)
160 .background(background)
161 .corner_radius(corner_radius)
162 .children(self.children.clone())
163 }
164
165 fn render_key(&self) -> DiffKey {
166 self.key.clone().or(self.default_key())
167 }
168}