freya_components/
floating_tab.rs1use freya_core::prelude::*;
2
3use crate::{
4 activable_route_context::use_activable_route,
5 get_theme,
6 theming::component_themes::{
7 FloatingTabTheme,
8 FloatingTabThemePartial,
9 },
10};
11
12#[derive(Debug, Default, PartialEq, Clone, Copy)]
14pub enum TabStatus {
15 #[default]
17 Idle,
18 Hovering,
20}
21
22#[derive(Clone, PartialEq)]
23pub struct FloatingTab {
24 pub(crate) theme: Option<FloatingTabThemePartial>,
25 children: Vec<Element>,
26 on_press: Option<EventHandler<Event<PressEventData>>>,
28 key: DiffKey,
29}
30
31impl KeyExt for FloatingTab {
32 fn write_key(&mut self) -> &mut DiffKey {
33 &mut self.key
34 }
35}
36
37impl Default for FloatingTab {
38 fn default() -> Self {
39 Self::new()
40 }
41}
42
43impl ChildrenExt for FloatingTab {
44 fn get_children(&mut self) -> &mut Vec<Element> {
45 &mut self.children
46 }
47}
48
49#[cfg_attr(feature = "docs",
71 doc = embed_doc_image::embed_image!("floating_tab", "images/gallery_floating_tab.png")
72)]
73impl FloatingTab {
74 pub fn new() -> Self {
75 Self {
76 children: vec![],
77 theme: None,
78 on_press: None,
79 key: DiffKey::None,
80 }
81 }
82
83 pub fn get_theme(&self) -> Option<&FloatingTabThemePartial> {
85 self.theme.as_ref()
86 }
87
88 pub fn theme(mut self, theme: FloatingTabThemePartial) -> Self {
90 self.theme = Some(theme);
91 self
92 }
93}
94
95impl Component for FloatingTab {
96 fn render(&self) -> impl IntoElement {
97 let focus = use_focus();
98 let focus_status = use_focus_status(focus);
99 let mut status = use_state(TabStatus::default);
100 let is_active = use_activable_route();
101
102 let FloatingTabTheme {
103 background,
104 hover_background,
105 padding,
106 width,
107 height,
108 color,
109 corner_radius,
110 } = get_theme!(&self.theme, floating_tab);
111
112 let on_pointer_enter = move |_| {
113 Cursor::set(CursorIcon::Pointer);
114 status.set(TabStatus::Hovering);
115 };
116
117 let on_pointer_leave = move |_| {
118 Cursor::set(CursorIcon::default());
119 status.set(TabStatus::default());
120 };
121
122 let background = if focus_status() == FocusStatus::Keyboard
123 || is_active
124 || *status.read() == TabStatus::Hovering
125 {
126 hover_background
127 } else {
128 background
129 };
130
131 rect()
132 .a11y_id(focus.a11y_id())
133 .a11y_focusable(Focusable::Enabled)
134 .a11y_role(AccessibilityRole::Tab)
135 .on_pointer_enter(on_pointer_enter)
136 .on_pointer_leave(on_pointer_leave)
137 .map(self.on_press.clone(), |el, on_press| el.on_press(on_press))
138 .width(width)
139 .height(height)
140 .center()
141 .overflow(Overflow::Clip)
142 .padding(padding)
143 .background(background)
144 .color(color)
145 .corner_radius(corner_radius)
146 .children(self.children.clone())
147 }
148
149 fn render_key(&self) -> DiffKey {
150 self.key.clone().or(self.default_key())
151 }
152}