1use gpui::{AnyElement, Div, StyleRefinement};
2use smallvec::SmallVec;
3use ui::{ButtonLike, prelude::*};
4
5#[derive(IntoElement)]
6pub struct FeatureUpsell {
7 base: Div,
8 text: SharedString,
9 docs_url: Option<SharedString>,
10 children: SmallVec<[AnyElement; 2]>,
11}
12
13impl FeatureUpsell {
14 pub fn new(text: impl Into<SharedString>) -> Self {
15 Self {
16 base: h_flex(),
17 text: text.into(),
18 docs_url: None,
19 children: SmallVec::new(),
20 }
21 }
22
23 pub fn docs_url(mut self, docs_url: impl Into<SharedString>) -> Self {
24 self.docs_url = Some(docs_url.into());
25 self
26 }
27}
28
29impl ParentElement for FeatureUpsell {
30 fn extend(&mut self, elements: impl IntoIterator<Item = AnyElement>) {
31 self.children.extend(elements)
32 }
33}
34
35// Style methods.
36impl FeatureUpsell {
37 fn style(&mut self) -> &mut StyleRefinement {
38 self.base.style()
39 }
40
41 gpui::border_style_methods!({
42 visibility: pub
43 });
44}
45
46impl RenderOnce for FeatureUpsell {
47 fn render(self, _window: &mut Window, cx: &mut App) -> impl IntoElement {
48 self.base
49 .p_4()
50 .justify_between()
51 .border_color(cx.theme().colors().border)
52 .child(v_flex().overflow_hidden().child(Label::new(self.text)))
53 .child(h_flex().gap_2().children(self.children).when_some(
54 self.docs_url,
55 |el, docs_url| {
56 el.child(
57 ButtonLike::new("open_docs")
58 .child(
59 h_flex()
60 .gap_2()
61 .child(Label::new("View docs"))
62 .child(Icon::new(IconName::ArrowUpRight)),
63 )
64 .on_click({
65 let docs_url = docs_url.clone();
66 move |_event, _window, cx| {
67 telemetry::event!(
68 "Documentation Viewed",
69 source = "Feature Upsell",
70 url = docs_url,
71 );
72 cx.open_url(&docs_url)
73 }
74 }),
75 )
76 },
77 ))
78 }
79}