egui_components/tooltip.rs
1//! `Tooltip` — themed hover help attached to any widget [`Response`].
2//!
3//! egui already renders tooltips in a framed popover; this wrapper styles the
4//! content with the component theme (foreground / muted colors, optional bold
5//! title) so it matches the rest of the library. Attach it to whatever a
6//! widget returns:
7//!
8//! ```ignore
9//! let r = sc::Tooltip::new("Delete this item")
10//! .attach(ui.add(sc::Button::danger("Delete")));
11//! ```
12
13use egui::{Response, Ui};
14
15use crate::common::Size;
16use crate::label::Label;
17
18pub struct Tooltip {
19 title: Option<String>,
20 text: String,
21 at_pointer: bool,
22}
23
24impl Tooltip {
25 pub fn new(text: impl Into<String>) -> Self {
26 Self {
27 title: None,
28 text: text.into(),
29 at_pointer: false,
30 }
31 }
32
33 /// Add a bold title line above the body text.
34 pub fn title(mut self, t: impl Into<String>) -> Self {
35 self.title = Some(t.into());
36 self
37 }
38
39 /// Anchor the tooltip to the pointer instead of the widget.
40 pub fn at_pointer(mut self) -> Self {
41 self.at_pointer = true;
42 self
43 }
44
45 /// Attach the tooltip to `response`, shown while the widget is hovered.
46 /// Returns the (possibly updated) [`Response`].
47 pub fn attach(self, response: Response) -> Response {
48 let Tooltip {
49 title,
50 text,
51 at_pointer,
52 } = self;
53 let add = move |ui: &mut Ui| {
54 ui.set_max_width(280.0);
55 if let Some(title) = &title {
56 ui.add(Label::new(title.clone()).strong().size(Size::Small));
57 }
58 ui.add(Label::new(text.clone()).size(Size::Small));
59 };
60 if at_pointer {
61 response.on_hover_ui_at_pointer(add)
62 } else {
63 response.on_hover_ui(add)
64 }
65 }
66}