diff --git a/assets/icons/circle-x.svg b/assets/icons/circle-x.svg
new file mode 100644
index 00000000..803c8cbe
--- /dev/null
+++ b/assets/icons/circle-x.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/assets/icons/delete.svg b/assets/icons/delete.svg
new file mode 100644
index 00000000..d5b1541f
--- /dev/null
+++ b/assets/icons/delete.svg
@@ -0,0 +1 @@
+delete
\ No newline at end of file
diff --git a/assets/icons/search.svg b/assets/icons/search.svg
new file mode 100644
index 00000000..a59b6a0d
--- /dev/null
+++ b/assets/icons/search.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/crates/app/src/story_workspace.rs b/crates/app/src/story_workspace.rs
index 901fe3d6..f2ddd643 100644
--- a/crates/app/src/story_workspace.rs
+++ b/crates/app/src/story_workspace.rs
@@ -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)
diff --git a/crates/ui-story/src/button_story.rs b/crates/ui-story/src/button_story.rs
index d4adcdfa..52d4124e 100644
--- a/crates/ui-story/src/button_story.rs
+++ b/crates/ui-story/src/button_story.rs
@@ -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) -> impl IntoElement {
+ fn render(&mut self, cx: &mut ViewContext) -> impl IntoElement {
+ fn section(title: impl Into, cx: &ViewContext) -> 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),
),
)
}
diff --git a/crates/ui-story/src/checkbox_story.rs b/crates/ui-story/src/checkbox_story.rs
index 65cb443c..96321f8a 100644
--- a/crates/ui-story/src/checkbox_story.rs
+++ b/crates/ui-story/src/checkbox_story.rs
@@ -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),
diff --git a/crates/ui-story/src/picker_story.rs b/crates/ui-story/src/picker_story.rs
index f89f4e9a..63c86f10 100644
--- a/crates/ui-story/src/picker_story.rs
+++ b/crates/ui-story/src/picker_story.rs
@@ -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;
diff --git a/crates/ui-story/src/popover_story.rs b/crates/ui-story/src/popover_story.rs
index d0d6dd2b..0d5e160f 100644
--- a/crates/ui-story/src/popover_story.rs
+++ b/crates/ui-story/src/popover_story.rs
@@ -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),
)
diff --git a/crates/ui-story/src/tooltip_story.rs b/crates/ui-story/src/tooltip_story.rs
index 41ade7a2..5682e861 100644
--- a/crates/ui-story/src/tooltip_story.rs
+++ b/crates/ui-story/src/tooltip_story.rs
@@ -25,14 +25,18 @@ impl TooltipStory {
}
impl Render for TooltipStory {
- fn render(&mut self, cx: &mut gpui::ViewContext) -> impl gpui::IntoElement {
+ fn render(&mut self, _cx: &mut gpui::ViewContext) -> 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),
)
diff --git a/crates/ui/src/button.rs b/crates/ui/src/button.rs
index ff8bfaf6..73f0521f 100644
--- a/crates/ui/src/button.rs
+++ b/crates/ui/src/button.rs
@@ -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,
- label: SharedString,
+ label: Option,
disabled: bool,
selected: bool,
width: Option,
@@ -47,12 +48,12 @@ pub struct Button {
}
impl Button {
- pub fn new(id: impl Into, label: impl Into) -> Self {
+ pub fn new(id: impl Into) -> 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, label: impl Into) -> Self {
- Self::new(id, label).style(ButtonStyle::Primary)
+ Self::new(id).label(label).style(ButtonStyle::Primary)
}
pub fn danger(id: impl Into, label: impl Into) -> Self {
- Self::new(id, label).style(ButtonStyle::Danger)
+ Self::new(id).label(label).style(ButtonStyle::Danger)
}
pub fn small(id: impl Into, label: impl Into) -> Self {
- Self::new(id, label).size(ButtonSize::Small)
+ Self::new(id).label(label).size(ButtonSize::Small)
}
pub fn width(mut self, width: impl Into) -> Self {
@@ -97,6 +98,12 @@ impl Button {
self
}
+ pub fn label(mut self, label: impl Into) -> 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) -> 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 }
}
diff --git a/crates/ui/src/checkbox.rs b/crates/ui/src/checkbox.rs
index 427a11d1..5bfbb671 100644
--- a/crates/ui/src/checkbox.rs
+++ b/crates/ui/src/checkbox.rs
@@ -23,7 +23,7 @@ pub struct Checkbox {
}
impl Checkbox {
- pub fn new(id: impl Into, _: &mut WindowContext) -> Self {
+ pub fn new(id: impl Into) -> Self {
Self {
id: id.into(),
checked: Selection::Unselected,
diff --git a/crates/ui/src/icon.rs b/crates/ui/src/icon.rs
index a4f949d6..2e9f7ea0 100644
--- a/crates/ui/src/icon.rs
+++ b/crates/ui/src/icon.rs
@@ -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,
+ 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)
}
}
diff --git a/crates/ui/src/switch.rs b/crates/ui/src/switch.rs
index ebae3cfa..ab5c929c 100644
--- a/crates/ui/src/switch.rs
+++ b/crates/ui/src/switch.rs
@@ -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);
+ })
},
)
}
diff --git a/crates/ui/src/theme.rs b/crates/ui/src/theme.rs
index dd34c284..92516f64 100644
--- a/crates/ui/src/theme.rs
+++ b/crates/ui/src/theme.rs
@@ -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 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,