use gpui::{ div, ClickEvent, Div, ElementId, InteractiveElement, IntoElement, MouseButton, ParentElement, RenderOnce, SharedString, Stateful, StatefulInteractiveElement, Styled, }; use crate::theme::ActiveTheme as _; type OnClick = Option>; /// A Link element like a `` tag in HTML. #[derive(IntoElement)] pub struct Link { base: Stateful
, href: Option, disabled: bool, on_click: OnClick, } impl Link { pub fn new(id: impl Into) -> Self { Self { base: div().id(id), href: None, on_click: None, disabled: false, } } pub fn href(mut self, href: impl Into) -> Self { self.href = Some(href.into()); self } pub fn on_click( mut self, handler: impl Fn(&ClickEvent, &mut gpui::WindowContext) + 'static, ) -> Self { self.on_click = Some(Box::new(handler)); self } pub fn disabled(mut self, disabled: bool) -> Self { self.disabled = disabled; self } } impl Styled for Link { fn style(&mut self) -> &mut gpui::StyleRefinement { self.base.style() } } impl ParentElement for Link { fn extend(&mut self, elements: impl IntoIterator) { self.base.extend(elements) } } impl RenderOnce for Link { fn render(self, cx: &mut gpui::WindowContext) -> impl IntoElement { let href = self.href.clone(); let on_click = self.on_click; div() .text_color(cx.theme().link) .text_decoration_1() .text_decoration_color(cx.theme().link) .hover(|this| { this.text_color(cx.theme().link.opacity(0.8)) .text_decoration_1() }) .cursor_pointer() .child( self.base .active(|this| { this.text_color(cx.theme().link.opacity(0.6)) .text_decoration_1() }) .on_mouse_down(MouseButton::Left, |_, cx| { cx.stop_propagation(); }) .on_click({ move |e, cx| { if let Some(href) = &href { cx.open_url(&href.clone()); } if let Some(on_click) = &on_click { on_click(e, cx); } } }), ) } }