Add Icon Button support. (#11)
When the Button have no label present, it will use the Icon mode. <img width="891" alt="image" src="https://github.com/huacnlee/gpui-component/assets/5518/ca6240d5-02c8-4201-9a79-4afdf9938dd8">
This commit is contained in:
parent
f9e075113e
commit
cbbd20867f
14 changed files with 358 additions and 147 deletions
1
assets/icons/circle-x.svg
Normal file
1
assets/icons/circle-x.svg
Normal file
|
|
@ -0,0 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-circle-x"><circle cx="12" cy="12" r="10"/><path d="m15 9-6 6"/><path d="m9 9 6 6"/></svg>
|
||||
|
After Width: | Height: | Size: 291 B |
1
assets/icons/delete.svg
Normal file
1
assets/icons/delete.svg
Normal file
|
|
@ -0,0 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-delete"><path d="M20 5H9l-7 7 7 7h11a2 2 0 0 0 2-2V7a2 2 0 0 0-2-2Z"/><line x1="18" x2="12" y1="9" y2="15"/><line x1="12" x2="18" y1="9" y2="15"/></svg>delete
|
||||
|
After Width: | Height: | Size: 360 B |
1
assets/icons/search.svg
Normal file
1
assets/icons/search.svg
Normal file
|
|
@ -0,0 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-search"><circle cx="11" cy="11" r="8"/><path d="m21 21-4.3-4.3"/></svg>
|
||||
|
After Width: | Height: | Size: 273 B |
|
|
@ -218,7 +218,7 @@ impl Render for StoryWorkspace {
|
|||
.items_center()
|
||||
.justify_end()
|
||||
.px_2()
|
||||
.on_mouse_move(|_, cx| cx.stop_propagation())
|
||||
.mr_3()
|
||||
.child(
|
||||
Switch::new("theme-mode")
|
||||
.size(ButtonSize::Small)
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
use gpui::{
|
||||
px, ClickEvent, IntoElement, ParentElement as _, Render, Styled as _, View, ViewContext,
|
||||
VisualContext as _, WindowContext,
|
||||
div, ClickEvent, Div, IntoElement, ParentElement as _, Render, SharedString, Styled as _, View,
|
||||
ViewContext, VisualContext as _, WindowContext,
|
||||
};
|
||||
|
||||
use ui::{
|
||||
|
|
@ -21,117 +21,224 @@ impl ButtonStory {
|
|||
}
|
||||
|
||||
impl Render for ButtonStory {
|
||||
fn render(&mut self, _cx: &mut ViewContext<Self>) -> impl IntoElement {
|
||||
fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
|
||||
fn section(title: impl Into<SharedString>, cx: &ViewContext<ButtonStory>) -> Div {
|
||||
use ui::theme::ActiveTheme;
|
||||
let theme = cx.theme();
|
||||
|
||||
h_flex()
|
||||
.items_center()
|
||||
.gap_4()
|
||||
.p_4()
|
||||
.w_full()
|
||||
.rounded_lg()
|
||||
.border_1()
|
||||
.border_color(theme.border)
|
||||
.flex_wrap()
|
||||
.justify_around()
|
||||
.child(div().flex_none().w_full().child(title.into()))
|
||||
}
|
||||
|
||||
v_flex()
|
||||
.w_full()
|
||||
.justify_start()
|
||||
.gap_6()
|
||||
.child(
|
||||
v_flex()
|
||||
.w(px(360.))
|
||||
h_flex()
|
||||
.gap_6()
|
||||
.child(
|
||||
Button::new("button-1", "Primary Button")
|
||||
.style(ButtonStyle::Primary)
|
||||
.on_click(Self::on_click),
|
||||
section("Normal Button", cx)
|
||||
.child(
|
||||
Button::new("button-1")
|
||||
.label("Primary Button")
|
||||
.style(ButtonStyle::Primary)
|
||||
.on_click(Self::on_click),
|
||||
)
|
||||
.child(
|
||||
Button::new("button-2")
|
||||
.label("Secondary Button")
|
||||
.style(ButtonStyle::Secondary)
|
||||
.on_click(Self::on_click),
|
||||
)
|
||||
.child(
|
||||
Button::new("button-4")
|
||||
.label("Danger Button")
|
||||
.style(ButtonStyle::Danger)
|
||||
.on_click(Self::on_click),
|
||||
),
|
||||
)
|
||||
.child(
|
||||
Button::new("button-2", "Secondary Button")
|
||||
.style(ButtonStyle::Secondary)
|
||||
.on_click(Self::on_click),
|
||||
)
|
||||
.child(
|
||||
Button::new("button-4", "Danger Button")
|
||||
.style(ButtonStyle::Danger)
|
||||
.on_click(Self::on_click),
|
||||
section("Button with Icon", cx)
|
||||
.child(
|
||||
Button::new("button-icon-1")
|
||||
.label("Confirm")
|
||||
.icon(IconName::Check)
|
||||
.style(ButtonStyle::Primary)
|
||||
.on_click(Self::on_click),
|
||||
)
|
||||
.child(
|
||||
Button::new("button-icon-2")
|
||||
.label("Abort")
|
||||
.icon(IconName::Close)
|
||||
.style(ButtonStyle::Secondary)
|
||||
.on_click(Self::on_click),
|
||||
)
|
||||
.child(
|
||||
Button::new("button-icon-3")
|
||||
.label("Maximize")
|
||||
.icon(Icon::new(IconName::Maximize))
|
||||
.style(ButtonStyle::Secondary)
|
||||
.on_click(Self::on_click),
|
||||
),
|
||||
),
|
||||
)
|
||||
.child(
|
||||
h_flex()
|
||||
.gap_6()
|
||||
.child(
|
||||
Button::new("button-icon-1", "Confirm")
|
||||
.icon(IconName::Check)
|
||||
.style(ButtonStyle::Primary)
|
||||
.on_click(Self::on_click),
|
||||
section("Small Size", cx)
|
||||
.child(
|
||||
Button::new("button-6")
|
||||
.label("Primary Button")
|
||||
.style(ButtonStyle::Primary)
|
||||
.size(ButtonSize::Small)
|
||||
.on_click(Self::on_click),
|
||||
)
|
||||
.child(
|
||||
Button::new("button-7")
|
||||
.label("Secondary Button")
|
||||
.style(ButtonStyle::Secondary)
|
||||
.size(ButtonSize::Small)
|
||||
.on_click(Self::on_click),
|
||||
)
|
||||
.child(
|
||||
Button::new("button-8")
|
||||
.label("Danger Button")
|
||||
.style(ButtonStyle::Danger)
|
||||
.size(ButtonSize::Small)
|
||||
.on_click(Self::on_click),
|
||||
),
|
||||
)
|
||||
.child(
|
||||
Button::new("button-icon-2", "Abort")
|
||||
section("XSmall Size", cx)
|
||||
.child(
|
||||
Button::new("button-xs-1")
|
||||
.label("Primary Button")
|
||||
.style(ButtonStyle::Primary)
|
||||
.size(ButtonSize::XSmall)
|
||||
.on_click(Self::on_click),
|
||||
)
|
||||
.child(
|
||||
Button::new("button-xs-2")
|
||||
.label("Secondary Button")
|
||||
.style(ButtonStyle::Secondary)
|
||||
.size(ButtonSize::XSmall)
|
||||
.on_click(Self::on_click),
|
||||
)
|
||||
.child(
|
||||
Button::new("button-xs-3")
|
||||
.label("Danger Button")
|
||||
.style(ButtonStyle::Danger)
|
||||
.size(ButtonSize::XSmall)
|
||||
.on_click(Self::on_click),
|
||||
),
|
||||
),
|
||||
)
|
||||
.child(
|
||||
h_flex()
|
||||
.gap_6()
|
||||
.child(
|
||||
section("Disabled Button", cx)
|
||||
.child(
|
||||
Button::new("button-disabled1")
|
||||
.label("Disabled Button")
|
||||
.style(ButtonStyle::Primary)
|
||||
.on_click(Self::on_click)
|
||||
.disabled(true),
|
||||
)
|
||||
.child(
|
||||
Button::new("button-disabled1")
|
||||
.label("Disabled Button")
|
||||
.style(ButtonStyle::Secondary)
|
||||
.on_click(Self::on_click)
|
||||
.disabled(true),
|
||||
)
|
||||
.child(
|
||||
Button::new("button-disabled1")
|
||||
.label("Disabled Button")
|
||||
.style(ButtonStyle::Danger)
|
||||
.on_click(Self::on_click)
|
||||
.disabled(true),
|
||||
),
|
||||
)
|
||||
.child(
|
||||
section("Selected Style", cx)
|
||||
.child(
|
||||
Button::new("button-selected-1")
|
||||
.label("Selected Button")
|
||||
.style(ButtonStyle::Primary)
|
||||
.selected(true),
|
||||
)
|
||||
.child(
|
||||
Button::new("button-selected-2")
|
||||
.label("Selected Button")
|
||||
.style(ButtonStyle::Secondary)
|
||||
.selected(true),
|
||||
)
|
||||
.child(
|
||||
Button::new("button-selected-3")
|
||||
.label("Selected Button")
|
||||
.style(ButtonStyle::Danger)
|
||||
.selected(true),
|
||||
),
|
||||
),
|
||||
)
|
||||
.child(
|
||||
section("Icon Button", cx)
|
||||
.child(
|
||||
Button::new("icon-button-0")
|
||||
.icon(IconName::Search)
|
||||
.style(ButtonStyle::Primary),
|
||||
)
|
||||
.child(Button::new("icon-button-1").icon(IconName::Info))
|
||||
.child(
|
||||
Button::new("icon-button-2")
|
||||
.icon(IconName::Close)
|
||||
.style(ButtonStyle::Secondary)
|
||||
.on_click(Self::on_click),
|
||||
.style(ButtonStyle::Danger),
|
||||
)
|
||||
.child(
|
||||
Button::new("button-icon-3", "Maximize")
|
||||
.icon(Icon::new(IconName::Maximize))
|
||||
.style(ButtonStyle::Secondary)
|
||||
.on_click(Self::on_click),
|
||||
),
|
||||
)
|
||||
.child(
|
||||
h_flex()
|
||||
.items_center()
|
||||
.gap_6()
|
||||
.child(
|
||||
Button::new("button-disabled1", "Disabled Button")
|
||||
.style(ButtonStyle::Primary)
|
||||
.on_click(Self::on_click)
|
||||
.disabled(true),
|
||||
)
|
||||
.child(
|
||||
Button::new("button-disabled1", "Disabled Button")
|
||||
.style(ButtonStyle::Secondary)
|
||||
.on_click(Self::on_click)
|
||||
.disabled(true),
|
||||
)
|
||||
.child(
|
||||
Button::new("button-disabled1", "Disabled Button")
|
||||
.style(ButtonStyle::Danger)
|
||||
.on_click(Self::on_click)
|
||||
.disabled(true),
|
||||
),
|
||||
)
|
||||
.child(
|
||||
h_flex()
|
||||
.items_center()
|
||||
.gap_6()
|
||||
.child(
|
||||
Button::new("button-6", "Primary Button")
|
||||
.style(ButtonStyle::Primary)
|
||||
Button::new("icon-button-3")
|
||||
.icon(IconName::Search)
|
||||
.size(ButtonSize::Small)
|
||||
.on_click(Self::on_click),
|
||||
.style(ButtonStyle::Primary),
|
||||
)
|
||||
.child(
|
||||
Button::new("button-7", "Secondary Button")
|
||||
.style(ButtonStyle::Secondary)
|
||||
Button::new("icon-button-4")
|
||||
.icon(IconName::Info)
|
||||
.size(ButtonSize::Small),
|
||||
)
|
||||
.child(
|
||||
Button::new("icon-button-5")
|
||||
.icon(IconName::Close)
|
||||
.size(ButtonSize::Small)
|
||||
.on_click(Self::on_click),
|
||||
.style(ButtonStyle::Danger),
|
||||
)
|
||||
.child(
|
||||
Button::new("button-8", "Danger Button")
|
||||
.style(ButtonStyle::Danger)
|
||||
.size(ButtonSize::Small)
|
||||
.on_click(Self::on_click),
|
||||
),
|
||||
)
|
||||
.child(
|
||||
h_flex()
|
||||
.items_center()
|
||||
.gap_6()
|
||||
.child(
|
||||
Button::new("button-6", "Selected Button")
|
||||
.style(ButtonStyle::Primary)
|
||||
.selected(true),
|
||||
Button::new("icon-button-6")
|
||||
.icon(IconName::Search)
|
||||
.size(ButtonSize::XSmall)
|
||||
.style(ButtonStyle::Primary),
|
||||
)
|
||||
.child(
|
||||
Button::new("button-7", "Selected Button")
|
||||
.style(ButtonStyle::Secondary)
|
||||
.selected(true),
|
||||
Button::new("icon-button-7")
|
||||
.icon(IconName::Info)
|
||||
.size(ButtonSize::XSmall),
|
||||
)
|
||||
.child(
|
||||
Button::new("button-8", "Selected Button")
|
||||
.style(ButtonStyle::Danger)
|
||||
.selected(true),
|
||||
Button::new("icon-button-8")
|
||||
.icon(IconName::Close)
|
||||
.size(ButtonSize::XSmall)
|
||||
.style(ButtonStyle::Danger),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -39,13 +39,15 @@ impl Render for CheckboxStory {
|
|||
h_flex()
|
||||
.items_center()
|
||||
.gap_6()
|
||||
.child(Checkbox::new("check1", cx).checked(self.check1).on_click(
|
||||
cx.listener(|v, _, _| {
|
||||
v.check1 = v.check1.inverse();
|
||||
}),
|
||||
))
|
||||
.child(
|
||||
Checkbox::new("check2", cx)
|
||||
Checkbox::new("check1")
|
||||
.checked(self.check1)
|
||||
.on_click(cx.listener(|v, _, _| {
|
||||
v.check1 = v.check1.inverse();
|
||||
})),
|
||||
)
|
||||
.child(
|
||||
Checkbox::new("check2")
|
||||
.checked(self.check2)
|
||||
.label("Subscribe to newsletter")
|
||||
.on_click(cx.listener(|v, _, _| {
|
||||
|
|
@ -53,7 +55,7 @@ impl Render for CheckboxStory {
|
|||
})),
|
||||
)
|
||||
.child(
|
||||
Checkbox::new("check3", cx)
|
||||
Checkbox::new("check3")
|
||||
.checked(self.check3)
|
||||
.label("Remember me")
|
||||
.on_click(cx.listener(|v, _, _| {
|
||||
|
|
@ -68,19 +70,19 @@ impl Render for CheckboxStory {
|
|||
.items_center()
|
||||
.gap_6()
|
||||
.child(
|
||||
Checkbox::new("check3", cx)
|
||||
Checkbox::new("check3")
|
||||
.label("Disabled Checked")
|
||||
.checked(Selection::Selected)
|
||||
.disabled(true),
|
||||
)
|
||||
.child(
|
||||
Checkbox::new("check3_1", cx)
|
||||
Checkbox::new("check3_1")
|
||||
.label("Disabled Unchecked")
|
||||
.checked(Selection::Unselected)
|
||||
.disabled(true),
|
||||
)
|
||||
.child(
|
||||
Checkbox::new("check3_2", cx)
|
||||
Checkbox::new("check3_2")
|
||||
.label("Disabled Indeterminate")
|
||||
.checked(Selection::Indeterminate)
|
||||
.disabled(true),
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ use ui::{
|
|||
h_flex,
|
||||
list::ListItem,
|
||||
picker::{Picker, PickerDelegate},
|
||||
v_flex, Clickable as _,
|
||||
v_flex, Clickable as _, IconName,
|
||||
};
|
||||
|
||||
actions!(picker_story, [DismissPicker]);
|
||||
|
|
@ -197,7 +197,9 @@ impl Render for PickerStory {
|
|||
.gap_6()
|
||||
.child(
|
||||
v_flex().items_start().child(
|
||||
Button::new("show-picker", "Show Picker...")
|
||||
Button::new("show-picker")
|
||||
.label("Show Picker...")
|
||||
.icon(IconName::Search)
|
||||
.style(ButtonStyle::Primary)
|
||||
.on_click(cx.listener(|this, _, cx| {
|
||||
this.open = !this.open;
|
||||
|
|
|
|||
|
|
@ -75,7 +75,7 @@ impl Render for PopoverStory {
|
|||
.child(
|
||||
v_flex().gap_4().child(
|
||||
Popover::new("info-top-left")
|
||||
.trigger(Button::new("info-top-left", "Top Left"))
|
||||
.trigger(Button::new("info-top-left").label("Top Left"))
|
||||
.content(|cx| {
|
||||
PopoverContent::new(cx, |_| {
|
||||
v_flex()
|
||||
|
|
@ -83,7 +83,8 @@ impl Render for PopoverStory {
|
|||
.child("Hello, this is a Popover.")
|
||||
.child(Divider::horizontal())
|
||||
.child(
|
||||
Button::new("info1", "Yes")
|
||||
Button::new("info1")
|
||||
.label("Yes")
|
||||
.width(px(80.))
|
||||
.size(ButtonSize::Small),
|
||||
)
|
||||
|
|
@ -95,7 +96,7 @@ impl Render for PopoverStory {
|
|||
.child(
|
||||
Popover::new("info-top-right")
|
||||
.anchor(AnchorCorner::TopRight)
|
||||
.trigger(Button::new("info-top-right", "Top Right"))
|
||||
.trigger(Button::new("info-top-right").label("Top Right"))
|
||||
.content(|cx| {
|
||||
PopoverContent::new(cx, |_| {
|
||||
v_flex()
|
||||
|
|
@ -103,7 +104,8 @@ impl Render for PopoverStory {
|
|||
.child("Hello, this is a Popover on the Top Right.")
|
||||
.child(Divider::horizontal())
|
||||
.child(
|
||||
Button::new("info1", "Yes")
|
||||
Button::new("info1")
|
||||
.label("Yes")
|
||||
.width(px(80.))
|
||||
.size(ButtonSize::Small),
|
||||
)
|
||||
|
|
@ -120,14 +122,20 @@ impl Render for PopoverStory {
|
|||
.child(
|
||||
Popover::new("info-bottom-left")
|
||||
.anchor(AnchorCorner::BottomLeft)
|
||||
.trigger(Button::new("pop", "Popup with Form").width(px(300.)))
|
||||
.trigger(
|
||||
Button::new("pop").label("Popup with Form").width(px(300.)),
|
||||
)
|
||||
.content(move |_| form.clone()),
|
||||
)
|
||||
.child(
|
||||
Popover::new("info-bottom-right")
|
||||
.anchor(AnchorCorner::BottomRight)
|
||||
.mouse_button(MouseButton::Right)
|
||||
.trigger(Button::new("pop", "Mouse Right Click").width(px(300.)))
|
||||
.trigger(
|
||||
Button::new("pop")
|
||||
.label("Mouse Right Click")
|
||||
.width(px(300.)),
|
||||
)
|
||||
.content(|cx| {
|
||||
PopoverContent::new(cx, |_| {
|
||||
v_flex()
|
||||
|
|
@ -135,7 +143,8 @@ impl Render for PopoverStory {
|
|||
.child("Hello, this is a Popover on the Bottom Right.")
|
||||
.child(Divider::horizontal())
|
||||
.child(
|
||||
Button::new("info1", "Yes")
|
||||
Button::new("info1")
|
||||
.label("Yes")
|
||||
.width(px(80.))
|
||||
.size(ButtonSize::Small),
|
||||
)
|
||||
|
|
|
|||
|
|
@ -25,14 +25,18 @@ impl TooltipStory {
|
|||
}
|
||||
|
||||
impl Render for TooltipStory {
|
||||
fn render(&mut self, cx: &mut gpui::ViewContext<Self>) -> impl gpui::IntoElement {
|
||||
fn render(&mut self, _cx: &mut gpui::ViewContext<Self>) -> impl gpui::IntoElement {
|
||||
v_flex()
|
||||
.w(px(360.))
|
||||
.gap_5()
|
||||
.child(
|
||||
div()
|
||||
.cursor(CursorStyle::PointingHand)
|
||||
.child(Button::new("button", "Hover me").style(ButtonStyle::Primary))
|
||||
.child(
|
||||
Button::new("button")
|
||||
.label("Hover me")
|
||||
.style(ButtonStyle::Primary),
|
||||
)
|
||||
.id("tooltip-1")
|
||||
.tooltip(|cx| Tooltip::text("This is a Button", cx)),
|
||||
)
|
||||
|
|
@ -40,7 +44,8 @@ impl Render for TooltipStory {
|
|||
div()
|
||||
.cursor(CursorStyle::PointingHand)
|
||||
.child(
|
||||
Button::new("button-meta", "With meta, Hover me")
|
||||
Button::new("button-meta")
|
||||
.label("With meta, Hover me")
|
||||
.style(ButtonStyle::Primary),
|
||||
)
|
||||
.id("tooltip-2")
|
||||
|
|
@ -58,7 +63,7 @@ impl Render for TooltipStory {
|
|||
div()
|
||||
.cursor(CursorStyle::PointingHand)
|
||||
.child(
|
||||
Checkbox::new("check", cx)
|
||||
Checkbox::new("check")
|
||||
.label("Remember me")
|
||||
.checked(Selection::Selected),
|
||||
)
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@ pub enum ButtonRounded {
|
|||
|
||||
#[derive(Clone, Copy)]
|
||||
pub enum ButtonSize {
|
||||
XSmall,
|
||||
Small,
|
||||
Medium,
|
||||
}
|
||||
|
|
@ -34,7 +35,7 @@ pub struct Button {
|
|||
pub base: Div,
|
||||
id: ElementId,
|
||||
icon: Option<Icon>,
|
||||
label: SharedString,
|
||||
label: Option<SharedString>,
|
||||
disabled: bool,
|
||||
selected: bool,
|
||||
width: Option<DefiniteLength>,
|
||||
|
|
@ -47,12 +48,12 @@ pub struct Button {
|
|||
}
|
||||
|
||||
impl Button {
|
||||
pub fn new(id: impl Into<ElementId>, label: impl Into<SharedString>) -> Self {
|
||||
pub fn new(id: impl Into<ElementId>) -> Self {
|
||||
Self {
|
||||
base: div(),
|
||||
id: id.into(),
|
||||
icon: None,
|
||||
label: label.into(),
|
||||
label: None,
|
||||
disabled: false,
|
||||
selected: false,
|
||||
style: ButtonStyle::Secondary,
|
||||
|
|
@ -66,15 +67,15 @@ impl Button {
|
|||
}
|
||||
|
||||
pub fn primary(id: impl Into<ElementId>, label: impl Into<SharedString>) -> Self {
|
||||
Self::new(id, label).style(ButtonStyle::Primary)
|
||||
Self::new(id).label(label).style(ButtonStyle::Primary)
|
||||
}
|
||||
|
||||
pub fn danger(id: impl Into<ElementId>, label: impl Into<SharedString>) -> Self {
|
||||
Self::new(id, label).style(ButtonStyle::Danger)
|
||||
Self::new(id).label(label).style(ButtonStyle::Danger)
|
||||
}
|
||||
|
||||
pub fn small(id: impl Into<ElementId>, label: impl Into<SharedString>) -> Self {
|
||||
Self::new(id, label).size(ButtonSize::Small)
|
||||
Self::new(id).label(label).size(ButtonSize::Small)
|
||||
}
|
||||
|
||||
pub fn width(mut self, width: impl Into<DefiniteLength>) -> Self {
|
||||
|
|
@ -97,6 +98,12 @@ impl Button {
|
|||
self
|
||||
}
|
||||
|
||||
pub fn label(mut self, label: impl Into<SharedString>) -> Self {
|
||||
self.label = Some(label.into());
|
||||
self
|
||||
}
|
||||
|
||||
/// Set the icon of the button, if the Button have no label, the button well in Icon Button mode.
|
||||
pub fn icon(mut self, icon: impl Into<Icon>) -> Self {
|
||||
self.icon = Some(icon.into());
|
||||
self
|
||||
|
|
@ -147,9 +154,20 @@ impl RenderOnce for Button {
|
|||
.justify_center()
|
||||
.when_some(self.width, |this, width| this.w(width))
|
||||
.when_some(self.height, |this, height| this.h(height))
|
||||
.map(|this| match self.size {
|
||||
ButtonSize::Small => this.px_3().py_2().h_6(),
|
||||
ButtonSize::Medium => this.px_4().py_2().h_8(),
|
||||
.map(|this| {
|
||||
if self.label.is_none() {
|
||||
match self.size {
|
||||
ButtonSize::XSmall => this.size_5(),
|
||||
ButtonSize::Small => this.size_6(),
|
||||
ButtonSize::Medium => this.size_8(),
|
||||
}
|
||||
} else {
|
||||
match self.size {
|
||||
ButtonSize::XSmall => this.px_1().py_1().h_5(),
|
||||
ButtonSize::Small => this.px_3().py_2().h_6(),
|
||||
ButtonSize::Medium => this.px_4().py_2().h_8(),
|
||||
}
|
||||
}
|
||||
})
|
||||
.map(|this| match self.rounded {
|
||||
ButtonRounded::Small => this.rounded(px(cx.theme().radius * 0.5)),
|
||||
|
|
@ -214,10 +232,11 @@ impl RenderOnce for Button {
|
|||
.gap_2()
|
||||
.text_color(text_color)
|
||||
.when_some(self.icon, |this, icon| {
|
||||
this.child(icon.text_color(text_color))
|
||||
this.child(icon.size(self.size).text_color(text_color))
|
||||
})
|
||||
.child(self.label)
|
||||
.when_some(self.label, |this, label| this.child(label))
|
||||
.map(|this| match self.size {
|
||||
ButtonSize::XSmall => this.text_xs(),
|
||||
ButtonSize::Small => this.text_sm(),
|
||||
ButtonSize::Medium => this.text_base(),
|
||||
})
|
||||
|
|
@ -250,9 +269,9 @@ impl ButtonStyle {
|
|||
|
||||
fn border_color(&self, cx: &WindowContext) -> Hsla {
|
||||
match self {
|
||||
ButtonStyle::Primary => cx.theme().primary.darken(0.05),
|
||||
ButtonStyle::Primary => cx.theme().primary,
|
||||
ButtonStyle::Secondary => cx.theme().border,
|
||||
ButtonStyle::Danger => cx.theme().destructive.darken(0.05),
|
||||
ButtonStyle::Danger => cx.theme().destructive,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -265,8 +284,11 @@ impl ButtonStyle {
|
|||
}
|
||||
|
||||
fn hovered(&self, cx: &WindowContext) -> ButtonStyles {
|
||||
// Hover color = color/90
|
||||
let bg = self.bg_color(cx);
|
||||
let bg = match self {
|
||||
ButtonStyle::Primary => cx.theme().primary_hover,
|
||||
ButtonStyle::Secondary => cx.theme().secondary_hover,
|
||||
ButtonStyle::Danger => cx.theme().destructive_hover,
|
||||
};
|
||||
let border = self.border_color(cx);
|
||||
let fg = self.text_color(cx);
|
||||
|
||||
|
|
@ -274,17 +296,25 @@ impl ButtonStyle {
|
|||
}
|
||||
|
||||
fn active(&self, cx: &WindowContext) -> ButtonStyles {
|
||||
let bg = self.bg_color(cx).darken(0.05);
|
||||
let bg = match self {
|
||||
ButtonStyle::Primary => cx.theme().primary_active,
|
||||
ButtonStyle::Secondary => cx.theme().secondary_active,
|
||||
ButtonStyle::Danger => cx.theme().destructive_active,
|
||||
};
|
||||
let border = self.border_color(cx);
|
||||
let fg = self.text_color(cx).darken(0.05);
|
||||
let fg = self.text_color(cx);
|
||||
|
||||
ButtonStyles { bg, border, fg }
|
||||
}
|
||||
|
||||
fn selected(&self, cx: &WindowContext) -> ButtonStyles {
|
||||
let bg = self.bg_color(cx).darken(0.07);
|
||||
let bg = match self {
|
||||
ButtonStyle::Primary => cx.theme().primary_active,
|
||||
ButtonStyle::Secondary => cx.theme().secondary_active,
|
||||
ButtonStyle::Danger => cx.theme().destructive_active,
|
||||
};
|
||||
let border = self.border_color(cx);
|
||||
let fg = self.text_color(cx).darken(0.07);
|
||||
let fg = self.text_color(cx);
|
||||
|
||||
ButtonStyles { bg, border, fg }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ pub struct Checkbox {
|
|||
}
|
||||
|
||||
impl Checkbox {
|
||||
pub fn new(id: impl Into<ElementId>, _: &mut WindowContext) -> Self {
|
||||
pub fn new(id: impl Into<ElementId>) -> Self {
|
||||
Self {
|
||||
id: id.into(),
|
||||
checked: Selection::Unselected,
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
use crate::theme::ActiveTheme;
|
||||
use crate::{button::ButtonSize, theme::ActiveTheme};
|
||||
use gpui::{
|
||||
svg, AnyElement, Hsla, IntoElement, RenderOnce, SharedString, StyleRefinement, Styled, Svg,
|
||||
WindowContext,
|
||||
prelude::FluentBuilder as _, svg, AnyElement, Hsla, IntoElement, RenderOnce, SharedString,
|
||||
StyleRefinement, Styled, Svg, WindowContext,
|
||||
};
|
||||
|
||||
#[derive(IntoElement)]
|
||||
|
|
@ -18,6 +18,9 @@ pub enum IconName {
|
|||
Info,
|
||||
Ellipsis,
|
||||
EllipsisVertical,
|
||||
Search,
|
||||
Delete,
|
||||
CicleX,
|
||||
}
|
||||
|
||||
impl IconName {
|
||||
|
|
@ -35,6 +38,9 @@ impl IconName {
|
|||
IconName::Info => "icons/info.svg",
|
||||
IconName::Ellipsis => "icons/ellipsis.svg",
|
||||
IconName::EllipsisVertical => "icons/ellipsis-vertical.svg",
|
||||
IconName::Search => "icons/search.svg",
|
||||
IconName::Delete => "icons/delete.svg",
|
||||
IconName::CicleX => "icons/circle-x.svg",
|
||||
}
|
||||
.into()
|
||||
}
|
||||
|
|
@ -57,6 +63,7 @@ pub struct Icon {
|
|||
base: Svg,
|
||||
path: SharedString,
|
||||
text_color: Option<Hsla>,
|
||||
size: ButtonSize,
|
||||
}
|
||||
|
||||
impl Icon {
|
||||
|
|
@ -65,6 +72,7 @@ impl Icon {
|
|||
base: svg().flex_none().size_4(),
|
||||
path: name.path(),
|
||||
text_color: None,
|
||||
size: ButtonSize::Medium,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -75,6 +83,12 @@ impl Icon {
|
|||
self.path = path.into();
|
||||
self
|
||||
}
|
||||
|
||||
pub fn size(mut self, size: ButtonSize) -> Self {
|
||||
self.size = size;
|
||||
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl Styled for Icon {
|
||||
|
|
@ -92,7 +106,14 @@ impl RenderOnce for Icon {
|
|||
fn render(self, cx: &mut WindowContext) -> impl IntoElement {
|
||||
let text_color = self.text_color.unwrap_or_else(|| cx.theme().foreground);
|
||||
|
||||
self.base.text_color(text_color).path(self.path)
|
||||
self.base
|
||||
.text_color(text_color)
|
||||
.map(|this| match self.size {
|
||||
ButtonSize::XSmall => this.size_3(),
|
||||
ButtonSize::Small => this.size_3p5(),
|
||||
ButtonSize::Medium => this.size_4(),
|
||||
})
|
||||
.path(self.path)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -109,7 +109,7 @@ impl RenderOnce for Switch {
|
|||
self.base
|
||||
.map(|this| match self.size {
|
||||
ButtonSize::Medium => this.w_11().h_6().rounded_xl(),
|
||||
ButtonSize::Small => this.w_8().h_4().rounded_lg(),
|
||||
ButtonSize::XSmall | ButtonSize::Small => this.w_8().h_4().rounded_lg(),
|
||||
})
|
||||
.flex()
|
||||
.items_center()
|
||||
|
|
@ -127,21 +127,24 @@ impl RenderOnce for Switch {
|
|||
.bg(toggle_bg)
|
||||
.map(|this| match self.size {
|
||||
ButtonSize::Medium => this.w_5().h_5(),
|
||||
ButtonSize::Small => this.w_3().h_3(),
|
||||
ButtonSize::XSmall | ButtonSize::Small => this.w_3().h_3(),
|
||||
}),
|
||||
),
|
||||
)
|
||||
.when_some(self.label, |this, label| {
|
||||
this.child(div().child(label).map(|this| match self.size {
|
||||
ButtonSize::Medium => this.text_base(),
|
||||
ButtonSize::Small => this.text_sm(),
|
||||
ButtonSize::XSmall | ButtonSize::Small => this.text_sm(),
|
||||
}))
|
||||
})
|
||||
.when_some(
|
||||
self.on_click.filter(|_| !self.disabled),
|
||||
|this, on_click| {
|
||||
cx.stop_propagation();
|
||||
this.on_click(move |ev, cx| on_click(ev, cx))
|
||||
this.on_click(move |ev, cx| {
|
||||
dbg!("---- switch clicked");
|
||||
cx.stop_propagation();
|
||||
on_click(ev, cx);
|
||||
})
|
||||
},
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -83,7 +83,6 @@ impl Colorize for Hsla {
|
|||
#[derive(Debug, Clone, Copy)]
|
||||
struct Colors {
|
||||
pub title_bar_background: Hsla,
|
||||
|
||||
pub background: Hsla,
|
||||
pub foreground: Hsla,
|
||||
pub card: Hsla,
|
||||
|
|
@ -91,15 +90,21 @@ struct Colors {
|
|||
pub popover: Hsla,
|
||||
pub popover_foreground: Hsla,
|
||||
pub primary: Hsla,
|
||||
pub primary_hover: Hsla,
|
||||
pub primary_active: Hsla,
|
||||
pub primary_foreground: Hsla,
|
||||
pub secondary: Hsla,
|
||||
pub secondary_hover: Hsla,
|
||||
pub secondary_active: Hsla,
|
||||
pub secondary_foreground: Hsla,
|
||||
pub destructive: Hsla,
|
||||
pub destructive_hover: Hsla,
|
||||
pub destructive_active: Hsla,
|
||||
pub destructive_foreground: Hsla,
|
||||
pub muted: Hsla,
|
||||
pub muted_foreground: Hsla,
|
||||
pub accent: Hsla,
|
||||
pub accent_foreground: Hsla,
|
||||
pub destructive: Hsla,
|
||||
pub destructive_foreground: Hsla,
|
||||
pub border: Hsla,
|
||||
pub input: Hsla,
|
||||
pub ring: Hsla,
|
||||
|
|
@ -145,15 +150,21 @@ impl Colors {
|
|||
popover: hsl(0.0, 0.0, 100.0),
|
||||
popover_foreground: hsl(240.0, 10.0, 3.9),
|
||||
primary: hsl(240.0, 5.9, 10.0),
|
||||
primary_hover: hsl(240.0, 5.9, 30.0),
|
||||
primary_active: hsl(240.0, 5.9, 45.0),
|
||||
primary_foreground: hsl(0.0, 0.0, 98.0),
|
||||
secondary: hsl(240.0, 4.8, 95.9),
|
||||
secondary_hover: hsl(240.0, 4.8, 99.),
|
||||
secondary_active: hsl(240.0, 5.9, 94.0),
|
||||
secondary_foreground: hsl(240.0, 59.0, 10.0),
|
||||
destructive: hsl(0.0, 84.2, 60.2),
|
||||
destructive_hover: hsl(0.0, 84.2, 65.0),
|
||||
destructive_active: hsl(0.0, 84.2, 47.0),
|
||||
destructive_foreground: hsl(0.0, 0.0, 98.0),
|
||||
muted: hsl(240.0, 4.8, 95.9),
|
||||
muted_foreground: hsl(240.0, 3.8, 46.1),
|
||||
accent: hsl(240.0, 5.0, 96.0),
|
||||
accent_foreground: hsl(240.0, 5.9, 10.0),
|
||||
destructive: hsl(0.0, 84.2, 60.2),
|
||||
destructive_foreground: hsl(0.0, 0.0, 98.0),
|
||||
border: hsl(240.0, 5.9, 90.0),
|
||||
input: hsl(240.0, 5.9, 90.0),
|
||||
ring: hsl(240.0, 5.9, 10.0),
|
||||
|
|
@ -198,15 +209,21 @@ impl Colors {
|
|||
popover: hsl(240.0, 10.0, 3.9),
|
||||
popover_foreground: hsl(0.0, 0.0, 98.0),
|
||||
primary: hsl(0.0, 0.0, 98.0),
|
||||
primary_hover: hsl(0.0, 0.0, 85.0),
|
||||
primary_active: hsl(0.0, 0.0, 60.0),
|
||||
primary_foreground: hsl(240.0, 5.9, 10.0),
|
||||
secondary: hsl(240.0, 3.7, 15.9),
|
||||
secondary_hover: hsl(240.0, 3.7, 20.9),
|
||||
secondary_active: hsl(240.0, 3.7, 8.9),
|
||||
secondary_foreground: hsl(0.0, 0.0, 98.0),
|
||||
destructive: hsl(0.0, 62.8, 30.6),
|
||||
destructive_hover: hsl(0.0, 62.8, 35.6),
|
||||
destructive_active: hsl(0.0, 62.8, 20.6),
|
||||
destructive_foreground: hsl(0.0, 0.0, 98.0),
|
||||
muted: hsl(240.0, 3.7, 15.9),
|
||||
muted_foreground: hsl(240.0, 5.0, 64.9),
|
||||
accent: hsl(240.0, 3.7, 15.9),
|
||||
accent_foreground: hsl(0.0, 0.0, 98.0),
|
||||
destructive: hsl(0.0, 62.8, 30.6),
|
||||
destructive_foreground: hsl(0.0, 0.0, 98.0),
|
||||
border: hsl(240.0, 3.7, 15.9),
|
||||
input: hsl(240.0, 3.7, 15.9),
|
||||
ring: hsl(240.0, 4.9, 83.9),
|
||||
|
|
@ -233,15 +250,21 @@ pub struct Theme {
|
|||
pub popover: Hsla,
|
||||
pub popover_foreground: Hsla,
|
||||
pub primary: Hsla,
|
||||
pub primary_hover: Hsla,
|
||||
pub primary_active: Hsla,
|
||||
pub primary_foreground: Hsla,
|
||||
pub secondary: Hsla,
|
||||
pub secondary_hover: Hsla,
|
||||
pub secondary_active: Hsla,
|
||||
pub secondary_foreground: Hsla,
|
||||
pub destructive: Hsla,
|
||||
pub destructive_hover: Hsla,
|
||||
pub destructive_active: Hsla,
|
||||
pub destructive_foreground: Hsla,
|
||||
pub muted: Hsla,
|
||||
pub muted_foreground: Hsla,
|
||||
pub accent: Hsla,
|
||||
pub accent_foreground: Hsla,
|
||||
pub destructive: Hsla,
|
||||
pub destructive_foreground: Hsla,
|
||||
pub border: Hsla,
|
||||
pub input: Hsla,
|
||||
pub ring: Hsla,
|
||||
|
|
@ -276,15 +299,21 @@ impl From<Colors> for Theme {
|
|||
popover: colors.popover,
|
||||
popover_foreground: colors.popover_foreground,
|
||||
primary: colors.primary,
|
||||
primary_hover: colors.primary_hover,
|
||||
primary_active: colors.primary_active,
|
||||
primary_foreground: colors.primary_foreground,
|
||||
secondary: colors.secondary,
|
||||
secondary_hover: colors.secondary_hover,
|
||||
secondary_active: colors.secondary_active,
|
||||
secondary_foreground: colors.secondary_foreground,
|
||||
destructive: colors.destructive,
|
||||
destructive_hover: colors.destructive_hover,
|
||||
destructive_active: colors.destructive_active,
|
||||
destructive_foreground: colors.destructive_foreground,
|
||||
muted: colors.muted,
|
||||
muted_foreground: colors.muted_foreground,
|
||||
accent: colors.accent,
|
||||
accent_foreground: colors.accent_foreground,
|
||||
destructive: colors.destructive,
|
||||
destructive_foreground: colors.destructive_foreground,
|
||||
border: colors.border,
|
||||
input: colors.input,
|
||||
ring: colors.ring,
|
||||
|
|
|
|||
Loading…
Reference in a new issue