1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
//! [`Tooltip`] — the small hover label.
//!
//! An entity rather than a function because gpui's `.tooltip(..)` takes a
//! builder returning an `AnyView`: the tooltip is mounted in its own layer,
//! after the hover delay, so it cannot be an inline element.
//!
//! ```ignore
//! use ui::tooltip::Tooltip;
//!
//! div()
//! .id("copy")
//! .tooltip(|window, cx| Tooltip::text("Copy path", window, cx))
//! .child("⌘C")
//! ```
use gpui::{AnyView, App, Context, IntoElement, SharedString, Window, div, prelude::*, px};
use theme::{TextStyle, Theme, Typeset};
use crate::{popover, surface::Surfaced as _};
pub struct Tooltip {
text: SharedString,
/// Optional keystroke shown right-aligned, e.g. `⌘C`.
keystroke: Option<SharedString>,
}
impl Tooltip {
/// A plain text tooltip, built for `.tooltip(..)`.
pub fn text(text: impl Into<SharedString>, _window: &mut Window, cx: &mut App) -> AnyView {
let text = text.into();
cx.new(|_| Self {
text,
keystroke: None,
})
.into()
}
/// A tooltip that also names the shortcut — the pairing that keeps
/// keyboard affordances discoverable without a menu.
pub fn with_keystroke(
text: impl Into<SharedString>,
keystroke: impl Into<SharedString>,
_window: &mut Window,
cx: &mut App,
) -> AnyView {
let (text, keystroke) = (text.into(), keystroke.into());
cx.new(|_| Self {
text,
keystroke: Some(keystroke),
})
.into()
}
}
impl Render for Tooltip {
fn render(&mut self, _window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
let theme = Theme::of(cx).clone();
// Tooltips are small and frequent, so this is a tighter card than
// `popover_card`: less padding, no menu rhythm.
popover::popover_card(&theme)
.px(px(8.0))
.py(px(5.0))
.flex()
.flex_row()
.items_center()
.gap(px(Theme::SPACE))
.text_style(TextStyle::Callout)
.text_color(theme.text)
.child(self.text.clone())
.when_some(self.keystroke.clone(), |card, keystroke| {
card.child(
div()
.text_style(TextStyle::Subheadline)
.text_color(theme.text_faint)
.child(keystroke),
)
})
.surface(&theme, theme.popover_surface)
}
}