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(PartialEq)]
23pub struct FloatingTab {
24 children: Vec<Element>,
25 pub(crate) theme: Option<FloatingTabThemePartial>,
26 on_press: Option<EventHandler<()>>,
28}
29
30impl Default for FloatingTab {
31 fn default() -> Self {
32 Self::new()
33 }
34}
35
36impl ChildrenExt for FloatingTab {
37 fn get_children(&mut self) -> &mut Vec<Element> {
38 &mut self.children
39 }
40}
41
42#[cfg_attr(feature = "docs",
67 doc = embed_doc_image::embed_image!("floating_tab", "images/gallery_floating_tab.png")
68)]
69impl FloatingTab {
70 pub fn new() -> Self {
71 Self {
72 children: vec![],
73 theme: None,
74 on_press: None,
75 }
76 }
77}
78
79impl Render for FloatingTab {
80 fn render(&self) -> impl IntoElement {
81 let focus = use_focus();
82 let focus_status = use_focus_status(focus);
83 let mut status = use_state(TabStatus::default);
84 let is_active = use_activable_route();
85
86 let FloatingTabTheme {
87 background,
88 hover_background,
89 padding,
90 width,
91 height,
92 color,
93 } = get_theme!(&self.theme, floating_tab);
94
95 let on_press = self.on_press.clone();
96
97 let on_press = move |_| {
98 if let Some(onpress) = &on_press {
99 onpress.call(());
100 }
101 };
102
103 let on_pointer_enter = move |_| {
104 Cursor::set(CursorIcon::Pointer);
105 status.set(TabStatus::Hovering);
106 };
107
108 let on_pointer_leave = move |_| {
109 Cursor::set(CursorIcon::default());
110 status.set(TabStatus::default());
111 };
112
113 let background = match *status.read() {
114 _ if focus_status() == FocusStatus::Keyboard || is_active => hover_background,
115 TabStatus::Hovering => hover_background,
116 TabStatus::Idle => background,
117 };
118
119 rect()
120 .on_press(on_press)
121 .on_pointer_enter(on_pointer_enter)
122 .on_pointer_leave(on_pointer_leave)
123 .a11y_id(focus.a11y_id())
124 .a11y_focusable(Focusable::Enabled)
125 .width(width)
126 .height(height)
127 .center()
128 .overflow(Overflow::Clip)
129 .padding(padding)
130 .background(background)
131 .color(color)
132 .corner_radius(99.)
133 .children(self.children.clone())
134 }
135}