1use gpui::{AnyView, App, Context, IntoElement, SharedString, Window, div, prelude::*, px};
23
24use crate::widgets::Content;
25use theme::{TextStyle, Theme, Typeset};
26
27use crate::{popover, surface::Surfaced as _};
28
29pub struct HoverCard {
30 title: SharedString,
31 body: SharedString,
32 initials: Option<SharedString>,
34 meta: Option<SharedString>,
36}
37
38impl HoverCard {
39 pub fn summary(
41 title: impl Into<SharedString>,
42 body: impl Into<SharedString>,
43 _window: &mut Window,
44 cx: &mut App,
45 ) -> AnyView {
46 let (title, body) = (title.into(), body.into());
47 cx.new(|_| Self {
48 title,
49 body,
50 initials: None,
51 meta: None,
52 })
53 .into()
54 }
55
56 pub fn person(
59 initials: impl Into<SharedString>,
60 name: impl Into<SharedString>,
61 body: impl Into<SharedString>,
62 meta: impl Into<SharedString>,
63 _window: &mut Window,
64 cx: &mut App,
65 ) -> AnyView {
66 let (initials, name, body, meta) = (initials.into(), name.into(), body.into(), meta.into());
67 cx.new(|_| Self {
68 title: name,
69 body,
70 initials: Some(initials),
71 meta: Some(meta),
72 })
73 .into()
74 }
75}
76
77impl Render for HoverCard {
78 fn render(&mut self, _window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
79 let theme = Theme::of(cx).clone();
80 let heading = div()
81 .flex()
82 .flex_row()
83 .items_center()
84 .gap(px(10.0))
85 .when_some(self.initials.clone(), |row, initials| {
86 row.child(theme.avatar(initials))
87 })
88 .child(
89 div()
90 .text_style(TextStyle::Headline)
91 .text_color(theme.text)
92 .child(self.title.clone()),
93 );
94
95 popover::popover_card(&theme)
97 .w(px(280.0))
98 .p(px(12.0))
99 .flex()
100 .flex_col()
101 .gap(px(Theme::SPACE))
102 .child(heading)
103 .child(
104 div()
105 .text_style(TextStyle::Callout)
106 .line_height(px(18.0))
107 .text_color(theme.text_muted)
108 .child(self.body.clone()),
109 )
110 .when_some(self.meta.clone(), |card, meta| {
111 card.child(
112 div()
113 .text_style(TextStyle::Subheadline)
114 .text_color(theme.text_faint)
115 .child(meta),
116 )
117 })
118 .surface(&theme, theme.popover_surface)
119 }
120}