Add Link (#91)

This commit is contained in:
Jason Lee 2024-07-31 14:24:57 +08:00 committed by GitHub
parent d659713555
commit d1c19c5912
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 118 additions and 12 deletions

View file

@ -22,6 +22,7 @@ A UI components for building desktop application by using [GPUI](https://gpui.rs
- [x] IconButton
- [x] Glost / Outline Button
- [x] Loading
- [x] Link
- [x] Label
- [x] Icon
- [x] Checkbox

View file

@ -1,9 +1,9 @@
use gpui::*;
use prelude::FluentBuilder as _;
use story::{
ButtonStory, CheckboxStory, DropdownStory, IconStory, ImageStory, InputStory, ListStory,
PickerStory, PopoverStory, ProgressStory, ResizableStory, ScrollableStory, StoryContainer,
SwitchStory, TableStory, TooltipStory,
ButtonStory, DropdownStory, IconStory, ImageStory, InputStory, ListStory, PickerStory,
PopoverStory, ProgressStory, ResizableStory, ScrollableStory, StoryContainer, SwitchStory,
TableStory, TextStory, TooltipStory,
};
use workspace::{TitleBar, Workspace};
@ -60,9 +60,9 @@ impl StoryWorkspace {
.detach();
StoryContainer::add_pane(
"Checkbox",
"A control that allows the user to toggle between checked and not checked.",
CheckboxStory::view(cx).into(),
"Text",
"Links, paragraphs, checkboxes, and more.",
TextStory::view(cx).into(),
workspace.clone(),
cx,
)

View file

@ -1,5 +1,4 @@
mod button_story;
mod checkbox_story;
mod dropdown_story;
mod icon_story;
mod image_story;
@ -12,11 +11,11 @@ mod resizable_story;
mod scrollable_story;
mod switch_story;
mod table_story;
mod text_story;
mod tooltip_story;
mod webview_story;
pub use button_story::ButtonStory;
pub use checkbox_story::CheckboxStory;
pub use dropdown_story::DropdownStory;
pub use icon_story::IconStory;
pub use image_story::ImageStory;
@ -29,6 +28,7 @@ pub use resizable_story::ResizableStory;
pub use scrollable_story::ScrollableStory;
pub use switch_story::SwitchStory;
pub use table_story::TableStory;
pub use text_story::TextStory;
pub use tooltip_story::TooltipStory;
pub use webview_story::WebViewStory;

View file

@ -8,13 +8,14 @@ use ui::{
checkbox::Checkbox,
h_flex,
label::Label,
link::Link,
radio::Radio,
v_flex, Clickable, Disableable as _, IconName, Selection, StyledExt,
};
use crate::section;
pub struct CheckboxStory {
pub struct TextStory {
check1: Selection,
check2: Selection,
check3: Selection,
@ -23,7 +24,7 @@ pub struct CheckboxStory {
masked: bool,
}
impl CheckboxStory {
impl TextStory {
pub(crate) fn new(_cx: &mut WindowContext) -> Self {
Self {
check1: Selection::Unselected,
@ -45,7 +46,7 @@ impl CheckboxStory {
}
}
impl Render for CheckboxStory {
impl Render for TextStory {
fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
v_flex()
.gap_6()
@ -74,7 +75,19 @@ impl Render for CheckboxStory {
.text_left()
.line_height(rems(1.8)),
),
),
)
)
.child(
section("Link", cx).child(
h_flex().items_start().gap_3()
.child(Link::new("link1").href("https://github.com").child("GitHub"))
.child(Link::new("link2").href("https://github.com").text_color(ui::red_500()).text_decoration_color(ui::red_500()).child("Red Link"))
.child(Link::new("link3").child(h_flex().gap_1().child(IconName::GitHub).child("GitHub")).on_click(cx.listener(|_, _, cx| {
cx.open_url("https://google.com")
})))
.child(div().w(px(250.)).child(Link::new("link4").child("https://github.com/huacnlee/gpui-component").href("https://github.com/huacnlee/gpui-component")))
)
)
.child(
section("Maksed Label", cx).child(

View file

@ -17,6 +17,7 @@ pub mod dropdown;
pub mod indicator;
pub mod input;
pub mod label;
pub mod link;
pub mod list;
pub mod popover;
pub mod popup_menu;

86
crates/ui/src/link.rs Normal file
View file

@ -0,0 +1,86 @@
use gpui::{
div, ClickEvent, Div, ElementId, InteractiveElement, IntoElement, MouseButton, ParentElement,
RenderOnce, SharedString, Stateful, StatefulInteractiveElement, Styled,
};
use crate::theme::{ActiveTheme as _, Colorize};
#[derive(IntoElement)]
pub struct Link {
base: Stateful<Div>,
href: Option<SharedString>,
on_click: Option<Box<dyn Fn(&ClickEvent, &mut gpui::WindowContext) + 'static>>,
}
impl Link {
pub fn new(id: impl Into<ElementId>) -> Self {
Self {
base: div().id(id),
href: None,
on_click: None,
}
}
pub fn href(mut self, href: impl Into<SharedString>) -> 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
}
}
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<Item = gpui::AnyElement>) {
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.prevent_default();
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);
}
}
}),
)
}
}

View file

@ -161,6 +161,7 @@ struct Colors {
pub list_even: Hsla,
pub list_active: Hsla,
pub list_head: Hsla,
pub link: Hsla,
}
impl Colors {
@ -201,6 +202,7 @@ impl Colors {
list_even: hsl(240.0, 5.0, 96.0),
list_active: hsl(240.0, 7., 88.0),
list_head: hsl(240.0, 0., 94.),
link: hsl(221.0, 83.0, 53.0),
}
}
@ -241,6 +243,7 @@ impl Colors {
list_even: hsl(240.0, 3.7, 8.0),
list_active: hsl(240.0, 3.7, 15.0),
list_head: hsl(240.0, 3.7, 10.9),
link: hsl(221.0, 83.0, 53.0),
}
}
}
@ -304,6 +307,7 @@ pub struct Theme {
pub table_head: Hsla,
pub table_active: Hsla,
pub table_hover: Hsla,
pub link: Hsla,
}
impl Global for Theme {}
@ -379,6 +383,7 @@ impl From<Colors> for Theme {
table_even: colors.list_even,
table_active: colors.list_active,
table_hover: colors.list_active.opacity(0.6),
link: colors.link,
}
}
}