feature_upsell.rs

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