Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .Jules/palette.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
## 2024-05-23 - Icon-Only Buttons and Tooltips
**Learning:** Icon-only buttons (like in the navigation bar) often lack text labels for space efficiency, but this hurts accessibility and usability for new users. Adding tooltips is a crucial micro-UX improvement.
**Action:** Always check `NavigationTabBar` and similar component-dense areas for icon-only buttons and ensure they emit `TooltipAction::HoverIn`/`HoverOut` events. Use `cx.display_context.is_desktop()` to position tooltips correctly (Right for desktop sidebar, Top for mobile bottom bar).
60 changes: 60 additions & 0 deletions src/home/navigation_tab_bar.rs
Original file line number Diff line number Diff line change
Expand Up @@ -473,6 +473,66 @@ impl Widget for NavigationTabBar {
fn handle_event(&mut self, cx: &mut Cx, event: &Event, scope: &mut Scope) {
self.view.handle_event(cx, event, scope);

let tooltip_pos = if cx.display_context.is_desktop() {
TooltipPosition::Right
} else {
TooltipPosition::Top
};

let buttons = [
(ids!(home_button), "Home"),
(ids!(add_room_button), "Add Room"),
(ids!(settings_button), "Settings"),
];

for (id, text) in buttons {
let button = self.view.radio_button(id);
match event.hits(cx, button.area()) {
Hit::FingerHoverIn(_) => {
cx.widget_action(
self.widget_uid(),
&scope.path,
TooltipAction::HoverIn {
text: text.to_string(),
widget_rect: button.area().rect(cx),
options: CalloutTooltipOptions {
position: tooltip_pos.clone(),
..Default::default()
},
},
);
}
Hit::FingerHoverOut(_) => {
cx.widget_action(self.widget_uid(), &scope.path, TooltipAction::HoverOut);
}
_ => {}
}
}

if !cx.display_context.is_desktop() {
let button = self.view.button(ids!(toggle_spaces_bar_button));
match event.hits(cx, button.area()) {
Hit::FingerHoverIn(_) => {
cx.widget_action(
self.widget_uid(),
&scope.path,
TooltipAction::HoverIn {
text: "Toggle Spaces".to_string(),
widget_rect: button.area().rect(cx),
options: CalloutTooltipOptions {
position: tooltip_pos.clone(),
..Default::default()
},
},
);
}
Hit::FingerHoverOut(_) => {
cx.widget_action(self.widget_uid(), &scope.path, TooltipAction::HoverOut);
}
_ => {}
}
}

if let Event::Actions(actions) = event {
// Handle one of the radio buttons being clicked (selected).
let radio_button_set = self.view.radio_button_set(ids_array!(
Expand Down