button_link.rs

  1use gpui::{IntoElement, Window, prelude::*};
  2
  3use crate::{ButtonLike, prelude::*};
  4
  5/// A button that takes an underline to look like a regular web link.
  6/// It also contains an arrow icon to communicate the link takes you out of Zed.
  7///
  8/// # Usage Example
  9///
 10/// ```
 11/// use ui::ButtonLink;
 12///
 13/// let button_link = ButtonLink::new("Click me", "https://example.com");
 14/// ```
 15#[derive(IntoElement, RegisterComponent)]
 16pub struct ButtonLink {
 17    label: SharedString,
 18    label_size: LabelSize,
 19    label_color: Color,
 20    link: String,
 21    no_icon: bool,
 22}
 23
 24impl ButtonLink {
 25    pub fn new(label: impl Into<SharedString>, link: impl Into<String>) -> Self {
 26        Self {
 27            link: link.into(),
 28            label: label.into(),
 29            label_size: LabelSize::Default,
 30            label_color: Color::Default,
 31            no_icon: false,
 32        }
 33    }
 34
 35    pub fn no_icon(mut self, no_icon: bool) -> Self {
 36        self.no_icon = no_icon;
 37        self
 38    }
 39
 40    pub fn label_size(mut self, label_size: LabelSize) -> Self {
 41        self.label_size = label_size;
 42        self
 43    }
 44
 45    pub fn label_color(mut self, label_color: Color) -> Self {
 46        self.label_color = label_color;
 47        self
 48    }
 49}
 50
 51impl RenderOnce for ButtonLink {
 52    fn render(self, _window: &mut Window, _cx: &mut App) -> impl IntoElement {
 53        let id = format!("{}-{}", self.label, self.link);
 54
 55        ButtonLike::new(id)
 56            .size(ButtonSize::None)
 57            .child(
 58                h_flex()
 59                    .gap_0p5()
 60                    .child(
 61                        Label::new(self.label)
 62                            .size(self.label_size)
 63                            .color(self.label_color)
 64                            .underline(),
 65                    )
 66                    .when(!self.no_icon, |this| {
 67                        this.child(
 68                            Icon::new(IconName::ArrowUpRight)
 69                                .size(IconSize::Small)
 70                                .color(Color::Muted),
 71                        )
 72                    }),
 73            )
 74            .on_click(move |_, _, cx| cx.open_url(&self.link))
 75            .into_any_element()
 76    }
 77}
 78
 79impl Component for ButtonLink {
 80    fn scope() -> ComponentScope {
 81        ComponentScope::Navigation
 82    }
 83
 84    fn description() -> Option<&'static str> {
 85        Some("A button that opens a URL.")
 86    }
 87
 88    fn preview(_window: &mut Window, _cx: &mut App) -> Option<AnyElement> {
 89        Some(
 90            v_flex()
 91                .gap_6()
 92                .child(
 93                    example_group(vec![single_example(
 94                        "Simple",
 95                        ButtonLink::new("zed.dev", "https://zed.dev").into_any_element(),
 96                    )])
 97                    .vertical(),
 98                )
 99                .into_any_element(),
100        )
101    }
102}