1use gpui::{overlay, Action, AnyView, IntoElement, Render, VisualContext};
2use settings::Settings;
3use theme::ThemeSettings;
4
5use crate::prelude::*;
6use crate::{h_flex, v_flex, Color, KeyBinding, Label, LabelSize, StyledExt};
7
8pub struct Tooltip {
9 title: SharedString,
10 meta: Option<SharedString>,
11 key_binding: Option<KeyBinding>,
12}
13
14impl Tooltip {
15 pub fn text(title: impl Into<SharedString>, cx: &mut WindowContext) -> AnyView {
16 cx.new_view(|_cx| Self {
17 title: title.into(),
18 meta: None,
19 key_binding: None,
20 })
21 .into()
22 }
23
24 pub fn for_action(
25 title: impl Into<SharedString>,
26 action: &dyn Action,
27 cx: &mut WindowContext,
28 ) -> AnyView {
29 cx.new_view(|cx| Self {
30 title: title.into(),
31 meta: None,
32 key_binding: KeyBinding::for_action(action, cx),
33 })
34 .into()
35 }
36
37 pub fn with_meta(
38 title: impl Into<SharedString>,
39 action: Option<&dyn Action>,
40 meta: impl Into<SharedString>,
41 cx: &mut WindowContext,
42 ) -> AnyView {
43 cx.new_view(|cx| Self {
44 title: title.into(),
45 meta: Some(meta.into()),
46 key_binding: action.and_then(|action| KeyBinding::for_action(action, cx)),
47 })
48 .into()
49 }
50
51 pub fn new(title: impl Into<SharedString>) -> Self {
52 Self {
53 title: title.into(),
54 meta: None,
55 key_binding: None,
56 }
57 }
58
59 pub fn meta(mut self, meta: impl Into<SharedString>) -> Self {
60 self.meta = Some(meta.into());
61 self
62 }
63
64 pub fn key_binding(mut self, key_binding: impl Into<Option<KeyBinding>>) -> Self {
65 self.key_binding = key_binding.into();
66 self
67 }
68}
69
70impl Render for Tooltip {
71 fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
72 let ui_font = ThemeSettings::get_global(cx).ui_font.family.clone();
73 overlay().child(
74 // padding to avoid mouse cursor
75 div().pl_2().pt_2p5().child(
76 v_flex()
77 .elevation_2(cx)
78 .font(ui_font)
79 .text_ui()
80 .text_color(cx.theme().colors().text)
81 .py_1()
82 .px_2()
83 .child(
84 h_flex()
85 .gap_4()
86 .child(self.title.clone())
87 .when_some(self.key_binding.clone(), |this, key_binding| {
88 this.justify_between().child(key_binding)
89 }),
90 )
91 .when_some(self.meta.clone(), |this, meta| {
92 this.child(Label::new(meta).size(LabelSize::Small).color(Color::Muted))
93 }),
94 ),
95 )
96 }
97}