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(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
108impl Component for SideBarItem {
109 fn render(&self) -> impl IntoElement {
110 let SideBarItemTheme {
111 margin,
112 hover_background,
113 active_background,
114 background,
115 corner_radius,
116 padding,
117 color,
118 } = get_theme!(&self.theme, sidebar_item);
119 let mut status = use_state(SideBarItemStatus::default);
120 let is_active = use_activable_route();
121
122 let on_pointer_enter = move |_| {
123 status.set(SideBarItemStatus::Hovering);
124 };
125
126 let on_pointer_leave = move |_| {
127 status.set(SideBarItemStatus::default());
128 };
129
130 let background = match *status.read() {
131 _ if is_active => active_background,
132 SideBarItemStatus::Hovering => hover_background,
133 SideBarItemStatus::Idle => background,
134 };
135
136 rect()
137 .a11y_focusable(true)
138 .a11y_role(AccessibilityRole::Link)
139 .map(self.on_press.clone(), |rect, on_press| {
140 rect.on_press(on_press)
141 })
142 .on_pointer_enter(on_pointer_enter)
143 .on_pointer_leave(on_pointer_leave)
144 .overflow(self.overflow)
145 .width(Size::fill())
146 .margin(margin)
147 .padding(padding)
148 .color(color)
149 .background(background)
150 .corner_radius(corner_radius)
151 .children(self.children.clone())
152 }
153
154 fn render_key(&self) -> DiffKey {
155 self.key.clone().or(self.default_key())
156 }
157}