1use gpui::{Action, AnyView, App, Context, IntoElement, SharedString, Window, div, prelude::*, px};
17
18use theme::{TextStyle, Theme, Typeset};
19
20use crate::{keys, popover, surface::Surfaced as _};
21
22pub struct Tooltip {
23 text: SharedString,
24 keystroke: Option<SharedString>,
26}
27
28impl Tooltip {
29 pub fn text(text: impl Into<SharedString>, _window: &mut Window, cx: &mut App) -> AnyView {
31 let text = text.into();
32 cx.new(|_| Self {
33 text,
34 keystroke: None,
35 })
36 .into()
37 }
38
39 pub fn with_keystroke(
42 text: impl Into<SharedString>,
43 keystroke: impl Into<SharedString>,
44 _window: &mut Window,
45 cx: &mut App,
46 ) -> AnyView {
47 let (text, keystroke) = (text.into(), keystroke.into());
48 cx.new(|_| Self {
49 text,
50 keystroke: Some(keystroke),
51 })
52 .into()
53 }
54
55 pub fn for_action(
64 text: impl Into<SharedString>,
65 action: &dyn Action,
66 window: &mut Window,
67 cx: &mut App,
68 ) -> AnyView {
69 let text = text.into();
70 let keystroke = keys::shortcut(action, window);
71 cx.new(|_| Self { text, keystroke }).into()
72 }
73
74 pub fn for_action_in(
77 text: impl Into<SharedString>,
78 action: &dyn Action,
79 context: &str,
80 window: &mut Window,
81 cx: &mut App,
82 ) -> AnyView {
83 let text = text.into();
84 let keystroke = keys::shortcut_in(action, context, window);
85 cx.new(|_| Self { text, keystroke }).into()
86 }
87}
88
89impl Render for Tooltip {
90 fn render(&mut self, _window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
91 let theme = Theme::of(cx).clone();
92 popover::popover_card(&theme)
95 .px(px(8.0))
96 .py(px(5.0))
97 .flex()
98 .flex_row()
99 .items_center()
100 .gap(px(Theme::SPACE))
101 .text_style(TextStyle::Callout)
102 .text_color(theme.text)
103 .child(self.text.clone())
104 .when_some(self.keystroke.clone(), |card, keystroke| {
105 card.child(
106 div()
107 .text_style(TextStyle::Subheadline)
108 .text_color(theme.text_faint)
109 .child(keystroke),
110 )
111 })
112 .surface(&theme, theme.popover_surface)
113 }
114}