Add Link (#91)
This commit is contained in:
parent
d659713555
commit
d1c19c5912
7 changed files with 118 additions and 12 deletions
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
)
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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(
|
||||
|
|
@ -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
86
crates/ui/src/link.rs
Normal 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);
|
||||
}
|
||||
}
|
||||
}),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -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,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue