freya_components/
floating_tab.rs1use freya_core::prelude::*;
2use torin::{
3 gaps::Gaps,
4 size::Size,
5};
6
7use crate::{
8 activable_context::use_is_active,
9 define_theme,
10 get_theme,
11};
12
13define_theme! {
14 %[component]
15 pub FloatingTab {
16 %[fields]
17 background: Color,
18 hover_background: Color,
19 width: Size,
20 height: Size,
21 padding: Gaps,
22 color: Color,
23 corner_radius: CornerRadius,
24 }
25}
26
27#[derive(Debug, Default, PartialEq, Clone, Copy)]
29pub enum TabStatus {
30 #[default]
32 Idle,
33 Hovering,
35}
36
37#[derive(Clone, PartialEq)]
38pub struct FloatingTab {
39 pub(crate) theme: Option<FloatingTabThemePartial>,
40 children: Vec<Element>,
41 on_press: Option<EventHandler<Event<PressEventData>>>,
43 key: DiffKey,
44}
45
46impl KeyExt for FloatingTab {
47 fn key_mut(&mut self) -> &mut DiffKey {
48 &mut self.key
49 }
50}
51
52impl Default for FloatingTab {
53 fn default() -> Self {
54 Self::new()
55 }
56}
57
58impl ChildrenExt for FloatingTab {
59 fn children_mut(&mut self) -> &mut Vec<Element> {
60 &mut self.children
61 }
62}
63
64impl FloatingTab {
80 pub fn new() -> Self {
81 Self {
82 children: vec![],
83 theme: None,
84 on_press: None,
85 key: DiffKey::None,
86 }
87 }
88
89 pub fn get_theme(&self) -> Option<&FloatingTabThemePartial> {
91 self.theme.as_ref()
92 }
93
94 pub fn theme(mut self, theme: FloatingTabThemePartial) -> Self {
96 self.theme = Some(theme);
97 self
98 }
99}
100
101impl Component for FloatingTab {
102 fn render(&self) -> impl IntoElement {
103 let a11y_id = use_a11y();
104 let focus = use_focus(a11y_id);
105 let mut status = use_state(TabStatus::default);
106 let is_active = use_is_active();
107
108 let FloatingTabTheme {
109 background,
110 hover_background,
111 padding,
112 width,
113 height,
114 color,
115 corner_radius,
116 } = get_theme!(&self.theme, FloatingTabThemePreference, "floating_tab");
117
118 let on_pointer_enter = move |_| {
119 status.set(TabStatus::Hovering);
120 };
121
122 let on_pointer_leave = move |_| {
123 status.set(TabStatus::default());
124 };
125
126 let background =
127 if focus() == Focus::Keyboard || is_active || *status.read() == TabStatus::Hovering {
128 hover_background
129 } else {
130 background
131 };
132
133 rect()
134 .a11y_id(a11y_id)
135 .a11y_focusable(Focusable::Enabled)
136 .a11y_role(AccessibilityRole::Tab)
137 .on_pointer_enter(on_pointer_enter)
138 .on_pointer_leave(on_pointer_leave)
139 .cursor(CursorIcon::Pointer)
140 .map(self.on_press.clone(), |el, on_press| el.on_press(on_press))
141 .width(width)
142 .height(height)
143 .center()
144 .overflow(Overflow::Clip)
145 .padding(padding)
146 .background(background)
147 .color(color)
148 .corner_radius(corner_radius)
149 .children(self.children.clone())
150 }
151
152 fn render_key(&self) -> DiffKey {
153 self.key.clone().or(self.default_key())
154 }
155}