button: Improve Button to support combine outline with other variants. (#714)
<img width="1385" alt="image" src="https://github.com/user-attachments/assets/240df695-bfd5-4680-89a2-2640db206b24" />
This commit is contained in:
parent
89170eea1d
commit
6da7de5299
5 changed files with 242 additions and 107 deletions
|
|
@ -4,7 +4,7 @@ use gpui::{
|
||||||
};
|
};
|
||||||
use gpui_component::{
|
use gpui_component::{
|
||||||
accordion::Accordion,
|
accordion::Accordion,
|
||||||
button::{Button, ButtonGroup, ButtonVariants as _},
|
button::{Button, ButtonGroup},
|
||||||
checkbox::Checkbox,
|
checkbox::Checkbox,
|
||||||
h_flex,
|
h_flex,
|
||||||
switch::Switch,
|
switch::Switch,
|
||||||
|
|
|
||||||
|
|
@ -4,10 +4,9 @@ use gpui::{
|
||||||
};
|
};
|
||||||
|
|
||||||
use gpui_component::{
|
use gpui_component::{
|
||||||
black,
|
|
||||||
button::{Button, ButtonCustomVariant, ButtonGroup, ButtonVariants as _, DropdownButton},
|
button::{Button, ButtonCustomVariant, ButtonGroup, ButtonVariants as _, DropdownButton},
|
||||||
checkbox::Checkbox,
|
checkbox::Checkbox,
|
||||||
green_500, green_600, green_800, green_900, green_950, h_flex, v_flex, white, ActiveTheme,
|
green_600, green_700, green_800, green_950, h_flex, v_flex, white, ActiveTheme,
|
||||||
Disableable as _, Icon, IconName, Selectable as _, Sizable as _, Theme,
|
Disableable as _, Icon, IconName, Selectable as _, Sizable as _, Theme,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -73,6 +72,33 @@ impl Render for ButtonStory {
|
||||||
let compact = self.compact;
|
let compact = self.compact;
|
||||||
let toggle_multiple = self.toggle_multiple;
|
let toggle_multiple = self.toggle_multiple;
|
||||||
|
|
||||||
|
let custom_variant = ButtonCustomVariant::new(cx)
|
||||||
|
.color(if cx.theme().mode.is_dark() {
|
||||||
|
green_800()
|
||||||
|
} else {
|
||||||
|
green_600()
|
||||||
|
})
|
||||||
|
.foreground(if cx.theme().mode.is_dark() {
|
||||||
|
white()
|
||||||
|
} else {
|
||||||
|
white()
|
||||||
|
})
|
||||||
|
.border(if cx.theme().mode.is_dark() {
|
||||||
|
green_800()
|
||||||
|
} else {
|
||||||
|
green_700()
|
||||||
|
})
|
||||||
|
.hover(if cx.theme().mode.is_dark() {
|
||||||
|
green_800()
|
||||||
|
} else {
|
||||||
|
green_600()
|
||||||
|
})
|
||||||
|
.active(if cx.theme().mode.is_dark() {
|
||||||
|
green_950()
|
||||||
|
} else {
|
||||||
|
green_700()
|
||||||
|
});
|
||||||
|
|
||||||
v_flex()
|
v_flex()
|
||||||
.on_action(cx.listener(|this, _: &Disabled, _, _| this.disabled = !this.disabled))
|
.on_action(cx.listener(|this, _: &Disabled, _, _| this.disabled = !this.disabled))
|
||||||
.on_action(cx.listener(|this, _: &Loading, _, _| this.loading = !this.loading))
|
.on_action(cx.listener(|this, _: &Loading, _, _| this.loading = !this.loading))
|
||||||
|
|
@ -165,16 +191,6 @@ impl Render for ButtonStory {
|
||||||
.when(compact, |this| this.compact())
|
.when(compact, |this| this.compact())
|
||||||
.on_click(Self::on_click),
|
.on_click(Self::on_click),
|
||||||
)
|
)
|
||||||
.child(
|
|
||||||
Button::new("button-5")
|
|
||||||
.outline()
|
|
||||||
.label("Outline Button")
|
|
||||||
.disabled(disabled)
|
|
||||||
.selected(selected)
|
|
||||||
.loading(loading)
|
|
||||||
.when(compact, |this| this.compact())
|
|
||||||
.on_click(Self::on_click),
|
|
||||||
)
|
|
||||||
.child(
|
.child(
|
||||||
Button::new("button-5-ghost")
|
Button::new("button-5-ghost")
|
||||||
.ghost()
|
.ghost()
|
||||||
|
|
@ -207,34 +223,7 @@ impl Render for ButtonStory {
|
||||||
)
|
)
|
||||||
.child(
|
.child(
|
||||||
Button::new("button-6-custom")
|
Button::new("button-6-custom")
|
||||||
.custom(
|
.custom(custom_variant)
|
||||||
ButtonCustomVariant::new(cx)
|
|
||||||
.color(if cx.theme().mode.is_dark() {
|
|
||||||
green_900()
|
|
||||||
} else {
|
|
||||||
green_500()
|
|
||||||
})
|
|
||||||
.foreground(if cx.theme().mode.is_dark() {
|
|
||||||
white()
|
|
||||||
} else {
|
|
||||||
black()
|
|
||||||
})
|
|
||||||
.border(if cx.theme().mode.is_dark() {
|
|
||||||
green_800()
|
|
||||||
} else {
|
|
||||||
green_600()
|
|
||||||
})
|
|
||||||
.hover(if cx.theme().mode.is_dark() {
|
|
||||||
green_800()
|
|
||||||
} else {
|
|
||||||
green_500()
|
|
||||||
})
|
|
||||||
.active(if cx.theme().mode.is_dark() {
|
|
||||||
green_950()
|
|
||||||
} else {
|
|
||||||
green_600()
|
|
||||||
}),
|
|
||||||
)
|
|
||||||
.label("Custom Button")
|
.label("Custom Button")
|
||||||
.disabled(disabled)
|
.disabled(disabled)
|
||||||
.selected(selected)
|
.selected(selected)
|
||||||
|
|
@ -328,6 +317,87 @@ impl Render for ButtonStory {
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
.child(
|
||||||
|
h_flex().gap_6().child(
|
||||||
|
section("Outline Button", cx)
|
||||||
|
.child(
|
||||||
|
Button::new("button-outline-1")
|
||||||
|
.primary()
|
||||||
|
.outline()
|
||||||
|
.label("Primary Button")
|
||||||
|
.disabled(disabled)
|
||||||
|
.selected(selected)
|
||||||
|
.loading(loading)
|
||||||
|
.when(compact, |this| this.compact())
|
||||||
|
.on_click(Self::on_click),
|
||||||
|
)
|
||||||
|
.child(
|
||||||
|
Button::new("button-outline-2")
|
||||||
|
.outline()
|
||||||
|
.label("Secondary Button")
|
||||||
|
.disabled(disabled)
|
||||||
|
.selected(selected)
|
||||||
|
.loading(loading)
|
||||||
|
.when(compact, |this| this.compact())
|
||||||
|
.on_click(Self::on_click),
|
||||||
|
)
|
||||||
|
.child(
|
||||||
|
Button::new("button-outline-4")
|
||||||
|
.danger()
|
||||||
|
.outline()
|
||||||
|
.label("Danger Button")
|
||||||
|
.disabled(disabled)
|
||||||
|
.selected(selected)
|
||||||
|
.loading(loading)
|
||||||
|
.when(compact, |this| this.compact())
|
||||||
|
.on_click(Self::on_click),
|
||||||
|
)
|
||||||
|
.child(
|
||||||
|
Button::new("button-outline-6-custom")
|
||||||
|
.outline()
|
||||||
|
.custom(custom_variant)
|
||||||
|
.label("Custom Button")
|
||||||
|
.disabled(disabled)
|
||||||
|
.selected(selected)
|
||||||
|
.loading(loading)
|
||||||
|
.when(compact, |this| this.compact())
|
||||||
|
.on_click(Self::on_click),
|
||||||
|
)
|
||||||
|
.child(
|
||||||
|
Button::new("button-outline-5-ghost")
|
||||||
|
.ghost()
|
||||||
|
.outline()
|
||||||
|
.label("Ghost Button")
|
||||||
|
.disabled(disabled)
|
||||||
|
.selected(selected)
|
||||||
|
.loading(loading)
|
||||||
|
.when(compact, |this| this.compact())
|
||||||
|
.on_click(Self::on_click),
|
||||||
|
)
|
||||||
|
.child(
|
||||||
|
Button::new("button-outline-5-link")
|
||||||
|
.link()
|
||||||
|
.outline()
|
||||||
|
.label("Link Button")
|
||||||
|
.disabled(disabled)
|
||||||
|
.selected(selected)
|
||||||
|
.loading(loading)
|
||||||
|
.when(compact, |this| this.compact())
|
||||||
|
.on_click(Self::on_click),
|
||||||
|
)
|
||||||
|
.child(
|
||||||
|
Button::new("button-outline-5-text")
|
||||||
|
.text()
|
||||||
|
.outline()
|
||||||
|
.label("Text Button")
|
||||||
|
.disabled(disabled)
|
||||||
|
.selected(selected)
|
||||||
|
.loading(loading)
|
||||||
|
.when(compact, |this| this.compact())
|
||||||
|
.on_click(Self::on_click),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)
|
||||||
.child(
|
.child(
|
||||||
h_flex()
|
h_flex()
|
||||||
.gap_6()
|
.gap_6()
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@ use gpui::{
|
||||||
ParentElement, Pixels, Render, ScrollHandle, SharedString, Size, Styled, Window,
|
ParentElement, Pixels, Render, ScrollHandle, SharedString, Size, Styled, Window,
|
||||||
};
|
};
|
||||||
use gpui_component::{
|
use gpui_component::{
|
||||||
button::{Button, ButtonGroup, ButtonVariants as _},
|
button::{Button, ButtonGroup},
|
||||||
divider::Divider,
|
divider::Divider,
|
||||||
gray_100, gray_800, h_flex,
|
gray_100, gray_800, h_flex,
|
||||||
label::Label,
|
label::Label,
|
||||||
|
|
|
||||||
|
|
@ -46,11 +46,6 @@ pub trait ButtonVariants: Sized {
|
||||||
self.with_variant(ButtonVariant::Danger)
|
self.with_variant(ButtonVariant::Danger)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// With the outline style for the Button.
|
|
||||||
fn outline(self) -> Self {
|
|
||||||
self.with_variant(ButtonVariant::Outline)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// With the ghost style for the Button.
|
/// With the ghost style for the Button.
|
||||||
fn ghost(self) -> Self {
|
fn ghost(self) -> Self {
|
||||||
self.with_variant(ButtonVariant::Ghost)
|
self.with_variant(ButtonVariant::Ghost)
|
||||||
|
|
@ -121,7 +116,6 @@ pub enum ButtonVariant {
|
||||||
Primary,
|
Primary,
|
||||||
Secondary,
|
Secondary,
|
||||||
Danger,
|
Danger,
|
||||||
Outline,
|
|
||||||
Ghost,
|
Ghost,
|
||||||
Link,
|
Link,
|
||||||
Text,
|
Text,
|
||||||
|
|
@ -160,6 +154,7 @@ pub struct Button {
|
||||||
pub(crate) selected: bool,
|
pub(crate) selected: bool,
|
||||||
variant: ButtonVariant,
|
variant: ButtonVariant,
|
||||||
rounded: ButtonRounded,
|
rounded: ButtonRounded,
|
||||||
|
outline: bool,
|
||||||
border_corners: Corners<bool>,
|
border_corners: Corners<bool>,
|
||||||
border_edges: Edges<bool>,
|
border_edges: Edges<bool>,
|
||||||
size: Size,
|
size: Size,
|
||||||
|
|
@ -196,11 +191,18 @@ impl Button {
|
||||||
stop_propagation: true,
|
stop_propagation: true,
|
||||||
loading: false,
|
loading: false,
|
||||||
compact: false,
|
compact: false,
|
||||||
|
outline: false,
|
||||||
children: Vec::new(),
|
children: Vec::new(),
|
||||||
loading_icon: None,
|
loading_icon: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Set the outline style of the Button.
|
||||||
|
pub fn outline(mut self) -> Self {
|
||||||
|
self.outline = true;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
/// Set the border radius of the Button.
|
/// Set the border radius of the Button.
|
||||||
pub fn rounded(mut self, rounded: impl Into<ButtonRounded>) -> Self {
|
pub fn rounded(mut self, rounded: impl Into<ButtonRounded>) -> Self {
|
||||||
self.rounded = rounded.into();
|
self.rounded = rounded.into();
|
||||||
|
|
@ -321,7 +323,7 @@ impl InteractiveElement for Button {
|
||||||
impl RenderOnce for Button {
|
impl RenderOnce for Button {
|
||||||
fn render(self, _window: &mut Window, cx: &mut App) -> impl IntoElement {
|
fn render(self, _window: &mut Window, cx: &mut App) -> impl IntoElement {
|
||||||
let style: ButtonVariant = self.variant;
|
let style: ButtonVariant = self.variant;
|
||||||
let normal_style = style.normal(cx);
|
let normal_style = style.normal(self.outline, cx);
|
||||||
let icon_size = match self.size {
|
let icon_size = match self.size {
|
||||||
Size::Size(v) => Size::Size(v * 0.75),
|
Size::Size(v) => Size::Size(v * 0.75),
|
||||||
_ => self.size,
|
_ => self.size,
|
||||||
|
|
@ -382,7 +384,7 @@ impl RenderOnce for Button {
|
||||||
.when(self.border_edges.bottom, |this| this.border_b_1())
|
.when(self.border_edges.bottom, |this| this.border_b_1())
|
||||||
.text_color(normal_style.fg)
|
.text_color(normal_style.fg)
|
||||||
.when(self.selected, |this| {
|
.when(self.selected, |this| {
|
||||||
let selected_style = style.selected(cx);
|
let selected_style = style.selected(self.outline, cx);
|
||||||
this.bg(selected_style.bg)
|
this.bg(selected_style.bg)
|
||||||
.border_color(selected_style.border)
|
.border_color(selected_style.border)
|
||||||
.text_color(selected_style.fg)
|
.text_color(selected_style.fg)
|
||||||
|
|
@ -392,13 +394,13 @@ impl RenderOnce for Button {
|
||||||
.bg(normal_style.bg)
|
.bg(normal_style.bg)
|
||||||
.when(normal_style.underline, |this| this.text_decoration_1())
|
.when(normal_style.underline, |this| this.text_decoration_1())
|
||||||
.hover(|this| {
|
.hover(|this| {
|
||||||
let hover_style = style.hovered(cx);
|
let hover_style = style.hovered(self.outline, cx);
|
||||||
this.bg(hover_style.bg)
|
this.bg(hover_style.bg)
|
||||||
.border_color(hover_style.border)
|
.border_color(hover_style.border)
|
||||||
.text_color(crate::red_400())
|
.text_color(crate::red_400())
|
||||||
})
|
})
|
||||||
.active(|this| {
|
.active(|this| {
|
||||||
let active_style = style.active(cx);
|
let active_style = style.active(self.outline, cx);
|
||||||
this.bg(active_style.bg)
|
this.bg(active_style.bg)
|
||||||
.border_color(active_style.border)
|
.border_color(active_style.border)
|
||||||
.text_color(active_style.fg)
|
.text_color(active_style.fg)
|
||||||
|
|
@ -420,7 +422,7 @@ impl RenderOnce for Button {
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
.when(self.disabled, |this| {
|
.when(self.disabled, |this| {
|
||||||
let disabled_style = style.disabled(cx);
|
let disabled_style = style.disabled(self.outline, cx);
|
||||||
this.cursor_not_allowed()
|
this.cursor_not_allowed()
|
||||||
.bg(disabled_style.bg)
|
.bg(disabled_style.bg)
|
||||||
.text_color(disabled_style.fg)
|
.text_color(disabled_style.fg)
|
||||||
|
|
@ -471,38 +473,56 @@ struct ButtonVariantStyle {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ButtonVariant {
|
impl ButtonVariant {
|
||||||
fn bg_color(&self, cx: &mut App) -> Hsla {
|
fn bg_color(&self, outline: bool, cx: &mut App) -> Hsla {
|
||||||
|
if outline {
|
||||||
|
return cx.theme().background;
|
||||||
|
}
|
||||||
|
|
||||||
match self {
|
match self {
|
||||||
ButtonVariant::Primary => cx.theme().primary,
|
ButtonVariant::Primary => cx.theme().primary,
|
||||||
ButtonVariant::Secondary => cx.theme().secondary,
|
ButtonVariant::Secondary => cx.theme().secondary,
|
||||||
ButtonVariant::Danger => cx.theme().danger,
|
ButtonVariant::Danger => cx.theme().danger,
|
||||||
ButtonVariant::Outline
|
ButtonVariant::Ghost | ButtonVariant::Link | ButtonVariant::Text => {
|
||||||
| ButtonVariant::Ghost
|
cx.theme().transparent
|
||||||
| ButtonVariant::Link
|
}
|
||||||
| ButtonVariant::Text => cx.theme().transparent,
|
|
||||||
ButtonVariant::Custom(colors) => colors.color,
|
ButtonVariant::Custom(colors) => colors.color,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn text_color(&self, cx: &mut App) -> Hsla {
|
fn text_color(&self, outline: bool, cx: &mut App) -> Hsla {
|
||||||
match self {
|
match self {
|
||||||
ButtonVariant::Primary => cx.theme().primary_foreground,
|
ButtonVariant::Primary => {
|
||||||
ButtonVariant::Secondary | ButtonVariant::Outline | ButtonVariant::Ghost => {
|
if outline {
|
||||||
cx.theme().secondary_foreground
|
cx.theme().primary
|
||||||
|
} else {
|
||||||
|
cx.theme().primary_foreground
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ButtonVariant::Secondary | ButtonVariant::Ghost => cx.theme().secondary_foreground,
|
||||||
|
ButtonVariant::Danger => {
|
||||||
|
if outline {
|
||||||
|
cx.theme().danger
|
||||||
|
} else {
|
||||||
|
cx.theme().danger_foreground
|
||||||
|
}
|
||||||
}
|
}
|
||||||
ButtonVariant::Danger => cx.theme().danger_foreground,
|
|
||||||
ButtonVariant::Link => cx.theme().link,
|
ButtonVariant::Link => cx.theme().link,
|
||||||
ButtonVariant::Text => cx.theme().foreground,
|
ButtonVariant::Text => cx.theme().foreground,
|
||||||
ButtonVariant::Custom(colors) => colors.foreground,
|
ButtonVariant::Custom(colors) => {
|
||||||
|
if outline {
|
||||||
|
colors.color
|
||||||
|
} else {
|
||||||
|
colors.foreground
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn border_color(&self, cx: &mut App) -> Hsla {
|
fn border_color(&self, _outline: bool, cx: &mut App) -> Hsla {
|
||||||
match self {
|
match self {
|
||||||
ButtonVariant::Primary => cx.theme().primary,
|
ButtonVariant::Primary => cx.theme().primary,
|
||||||
ButtonVariant::Secondary => cx.theme().border,
|
ButtonVariant::Secondary => cx.theme().border,
|
||||||
ButtonVariant::Danger => cx.theme().danger,
|
ButtonVariant::Danger => cx.theme().danger,
|
||||||
ButtonVariant::Outline => cx.theme().border,
|
|
||||||
ButtonVariant::Ghost | ButtonVariant::Link | ButtonVariant::Text => {
|
ButtonVariant::Ghost | ButtonVariant::Link | ButtonVariant::Text => {
|
||||||
cx.theme().transparent
|
cx.theme().transparent
|
||||||
}
|
}
|
||||||
|
|
@ -517,7 +537,7 @@ impl ButtonVariant {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn shadow(&self, _: &App) -> bool {
|
fn shadow(&self, _outline: bool, _: &App) -> bool {
|
||||||
match self {
|
match self {
|
||||||
ButtonVariant::Primary | ButtonVariant::Secondary | ButtonVariant::Danger => true,
|
ButtonVariant::Primary | ButtonVariant::Secondary | ButtonVariant::Danger => true,
|
||||||
ButtonVariant::Custom(c) => c.shadow,
|
ButtonVariant::Custom(c) => c.shadow,
|
||||||
|
|
@ -525,12 +545,12 @@ impl ButtonVariant {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn normal(&self, cx: &mut App) -> ButtonVariantStyle {
|
fn normal(&self, outline: bool, cx: &mut App) -> ButtonVariantStyle {
|
||||||
let bg = self.bg_color(cx);
|
let bg = self.bg_color(outline, cx);
|
||||||
let border = self.border_color(cx);
|
let border = self.border_color(outline, cx);
|
||||||
let fg = self.text_color(cx);
|
let fg = self.text_color(outline, cx);
|
||||||
let underline = self.underline(cx);
|
let underline = self.underline(cx);
|
||||||
let shadow = self.shadow(cx);
|
let shadow = self.shadow(outline, cx);
|
||||||
|
|
||||||
ButtonVariantStyle {
|
ButtonVariantStyle {
|
||||||
bg,
|
bg,
|
||||||
|
|
@ -541,11 +561,23 @@ impl ButtonVariant {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn hovered(&self, cx: &mut App) -> ButtonVariantStyle {
|
fn hovered(&self, outline: bool, cx: &mut App) -> ButtonVariantStyle {
|
||||||
let bg = match self {
|
let bg = match self {
|
||||||
ButtonVariant::Primary => cx.theme().primary_hover,
|
ButtonVariant::Primary => {
|
||||||
ButtonVariant::Secondary | ButtonVariant::Outline => cx.theme().secondary_hover,
|
if outline {
|
||||||
ButtonVariant::Danger => cx.theme().danger_hover,
|
cx.theme().secondary_hover
|
||||||
|
} else {
|
||||||
|
cx.theme().primary_hover
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ButtonVariant::Secondary => cx.theme().secondary_hover,
|
||||||
|
ButtonVariant::Danger => {
|
||||||
|
if outline {
|
||||||
|
cx.theme().secondary_hover
|
||||||
|
} else {
|
||||||
|
cx.theme().danger_hover
|
||||||
|
}
|
||||||
|
}
|
||||||
ButtonVariant::Ghost => {
|
ButtonVariant::Ghost => {
|
||||||
if cx.theme().mode.is_dark() {
|
if cx.theme().mode.is_dark() {
|
||||||
cx.theme().secondary.lighten(0.1).opacity(0.8)
|
cx.theme().secondary.lighten(0.1).opacity(0.8)
|
||||||
|
|
@ -555,15 +587,23 @@ impl ButtonVariant {
|
||||||
}
|
}
|
||||||
ButtonVariant::Link => cx.theme().transparent,
|
ButtonVariant::Link => cx.theme().transparent,
|
||||||
ButtonVariant::Text => cx.theme().transparent,
|
ButtonVariant::Text => cx.theme().transparent,
|
||||||
ButtonVariant::Custom(colors) => colors.hover,
|
ButtonVariant::Custom(colors) => {
|
||||||
|
if outline {
|
||||||
|
cx.theme().secondary_hover
|
||||||
|
} else {
|
||||||
|
colors.hover
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
let border = self.border_color(cx);
|
|
||||||
|
let border = self.border_color(outline, cx);
|
||||||
let fg = match self {
|
let fg = match self {
|
||||||
ButtonVariant::Link => cx.theme().link_hover,
|
ButtonVariant::Link => cx.theme().link_hover,
|
||||||
_ => self.text_color(cx),
|
_ => self.text_color(outline, cx),
|
||||||
};
|
};
|
||||||
|
|
||||||
let underline = self.underline(cx);
|
let underline = self.underline(cx);
|
||||||
let shadow = self.shadow(cx);
|
let shadow = self.shadow(outline, cx);
|
||||||
|
|
||||||
ButtonVariantStyle {
|
ButtonVariantStyle {
|
||||||
bg,
|
bg,
|
||||||
|
|
@ -574,10 +614,16 @@ impl ButtonVariant {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn active(&self, cx: &mut App) -> ButtonVariantStyle {
|
fn active(&self, outline: bool, cx: &mut App) -> ButtonVariantStyle {
|
||||||
let bg = match self {
|
let bg = match self {
|
||||||
ButtonVariant::Primary => cx.theme().primary_active,
|
ButtonVariant::Primary => {
|
||||||
ButtonVariant::Secondary | ButtonVariant::Outline => cx.theme().secondary_active,
|
if outline {
|
||||||
|
cx.theme().primary_active.opacity(0.1)
|
||||||
|
} else {
|
||||||
|
cx.theme().primary_active
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ButtonVariant::Secondary => cx.theme().secondary_active,
|
||||||
ButtonVariant::Ghost => {
|
ButtonVariant::Ghost => {
|
||||||
if cx.theme().mode.is_dark() {
|
if cx.theme().mode.is_dark() {
|
||||||
cx.theme().secondary.lighten(0.2).opacity(0.8)
|
cx.theme().secondary.lighten(0.2).opacity(0.8)
|
||||||
|
|
@ -585,19 +631,31 @@ impl ButtonVariant {
|
||||||
cx.theme().secondary.darken(0.2).opacity(0.8)
|
cx.theme().secondary.darken(0.2).opacity(0.8)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ButtonVariant::Danger => cx.theme().danger_active,
|
ButtonVariant::Danger => {
|
||||||
|
if outline {
|
||||||
|
cx.theme().danger_active.opacity(0.1)
|
||||||
|
} else {
|
||||||
|
cx.theme().danger_active
|
||||||
|
}
|
||||||
|
}
|
||||||
ButtonVariant::Link => cx.theme().transparent,
|
ButtonVariant::Link => cx.theme().transparent,
|
||||||
ButtonVariant::Text => cx.theme().transparent,
|
ButtonVariant::Text => cx.theme().transparent,
|
||||||
ButtonVariant::Custom(colors) => colors.active,
|
ButtonVariant::Custom(colors) => {
|
||||||
|
if outline {
|
||||||
|
colors.active.opacity(0.1)
|
||||||
|
} else {
|
||||||
|
colors.active
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
let border = self.border_color(cx);
|
let border = self.border_color(outline, cx);
|
||||||
let fg = match self {
|
let fg = match self {
|
||||||
ButtonVariant::Link => cx.theme().link_active,
|
ButtonVariant::Link => cx.theme().link_active,
|
||||||
ButtonVariant::Text => cx.theme().foreground.opacity(0.7),
|
ButtonVariant::Text => cx.theme().foreground.opacity(0.7),
|
||||||
_ => self.text_color(cx),
|
_ => self.text_color(outline, cx),
|
||||||
};
|
};
|
||||||
let underline = self.underline(cx);
|
let underline = self.underline(cx);
|
||||||
let shadow = self.shadow(cx);
|
let shadow = self.shadow(outline, cx);
|
||||||
|
|
||||||
ButtonVariantStyle {
|
ButtonVariantStyle {
|
||||||
bg,
|
bg,
|
||||||
|
|
@ -608,26 +666,24 @@ impl ButtonVariant {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn selected(&self, cx: &mut App) -> ButtonVariantStyle {
|
fn selected(&self, outline: bool, cx: &mut App) -> ButtonVariantStyle {
|
||||||
let bg = match self {
|
let bg = match self {
|
||||||
ButtonVariant::Primary => cx.theme().primary_active,
|
ButtonVariant::Primary => cx.theme().primary_active,
|
||||||
ButtonVariant::Secondary | ButtonVariant::Outline | ButtonVariant::Ghost => {
|
ButtonVariant::Secondary | ButtonVariant::Ghost => cx.theme().secondary_active,
|
||||||
cx.theme().secondary_active
|
|
||||||
}
|
|
||||||
ButtonVariant::Danger => cx.theme().danger_active,
|
ButtonVariant::Danger => cx.theme().danger_active,
|
||||||
ButtonVariant::Link => cx.theme().transparent,
|
ButtonVariant::Link => cx.theme().transparent,
|
||||||
ButtonVariant::Text => cx.theme().transparent,
|
ButtonVariant::Text => cx.theme().transparent,
|
||||||
ButtonVariant::Custom(colors) => colors.active,
|
ButtonVariant::Custom(colors) => colors.active,
|
||||||
};
|
};
|
||||||
|
|
||||||
let border = self.border_color(cx);
|
let border = self.border_color(outline, cx);
|
||||||
let fg = match self {
|
let fg = match self {
|
||||||
ButtonVariant::Link => cx.theme().link_active,
|
ButtonVariant::Link => cx.theme().link_active,
|
||||||
ButtonVariant::Text => cx.theme().foreground.opacity(0.7),
|
ButtonVariant::Text => cx.theme().foreground.opacity(0.7),
|
||||||
_ => self.text_color(cx),
|
_ => self.text_color(outline, cx),
|
||||||
};
|
};
|
||||||
let underline = self.underline(cx);
|
let underline = self.underline(cx);
|
||||||
let shadow = self.shadow(cx);
|
let shadow = self.shadow(outline, cx);
|
||||||
|
|
||||||
ButtonVariantStyle {
|
ButtonVariantStyle {
|
||||||
bg,
|
bg,
|
||||||
|
|
@ -638,12 +694,11 @@ impl ButtonVariant {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn disabled(&self, cx: &mut App) -> ButtonVariantStyle {
|
fn disabled(&self, outline: bool, cx: &mut App) -> ButtonVariantStyle {
|
||||||
let bg = match self {
|
let bg = match self {
|
||||||
ButtonVariant::Link
|
ButtonVariant::Link | ButtonVariant::Ghost | ButtonVariant::Text => {
|
||||||
| ButtonVariant::Ghost
|
cx.theme().transparent
|
||||||
| ButtonVariant::Outline
|
}
|
||||||
| ButtonVariant::Text => cx.theme().transparent,
|
|
||||||
ButtonVariant::Primary => cx.theme().primary.opacity(0.15),
|
ButtonVariant::Primary => cx.theme().primary.opacity(0.15),
|
||||||
ButtonVariant::Danger => cx.theme().danger.opacity(0.15),
|
ButtonVariant::Danger => cx.theme().danger.opacity(0.15),
|
||||||
ButtonVariant::Secondary => cx.theme().secondary.opacity(1.5),
|
ButtonVariant::Secondary => cx.theme().secondary.opacity(1.5),
|
||||||
|
|
@ -656,9 +711,10 @@ impl ButtonVariant {
|
||||||
_ => cx.theme().secondary_foreground.opacity(0.5).grayscale(),
|
_ => cx.theme().secondary_foreground.opacity(0.5).grayscale(),
|
||||||
};
|
};
|
||||||
|
|
||||||
let border = match self {
|
let (bg, border) = if outline {
|
||||||
ButtonVariant::Outline => cx.theme().border.opacity(0.5),
|
(cx.theme().transparent, cx.theme().border.opacity(0.5))
|
||||||
_ => bg,
|
} else {
|
||||||
|
(bg, bg)
|
||||||
};
|
};
|
||||||
|
|
||||||
let underline = self.underline(cx);
|
let underline = self.underline(cx);
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,8 @@ pub struct ButtonGroup {
|
||||||
pub(super) disabled: bool,
|
pub(super) disabled: bool,
|
||||||
|
|
||||||
// The button props
|
// The button props
|
||||||
pub(super) compact: Option<bool>,
|
pub(super) compact: bool,
|
||||||
|
pub(super) outline: bool,
|
||||||
pub(super) variant: Option<ButtonVariant>,
|
pub(super) variant: Option<ButtonVariant>,
|
||||||
pub(super) size: Option<Size>,
|
pub(super) size: Option<Size>,
|
||||||
|
|
||||||
|
|
@ -42,7 +43,8 @@ impl ButtonGroup {
|
||||||
id: id.into(),
|
id: id.into(),
|
||||||
variant: None,
|
variant: None,
|
||||||
size: None,
|
size: None,
|
||||||
compact: None,
|
compact: false,
|
||||||
|
outline: false,
|
||||||
multiple: false,
|
multiple: false,
|
||||||
disabled: false,
|
disabled: false,
|
||||||
on_click: None,
|
on_click: None,
|
||||||
|
|
@ -69,7 +71,13 @@ impl ButtonGroup {
|
||||||
|
|
||||||
/// With the compact mode for the ButtonGroup.
|
/// With the compact mode for the ButtonGroup.
|
||||||
pub fn compact(mut self) -> Self {
|
pub fn compact(mut self) -> Self {
|
||||||
self.compact = Some(true);
|
self.compact = true;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
/// With the outline mode for the ButtonGroup.
|
||||||
|
pub fn outline(mut self) -> Self {
|
||||||
|
self.outline = true;
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -193,7 +201,8 @@ impl RenderOnce for ButtonGroup {
|
||||||
.stop_propagation(false)
|
.stop_propagation(false)
|
||||||
.when_some(self.size, |this, size| this.with_size(size))
|
.when_some(self.size, |this, size| this.with_size(size))
|
||||||
.when_some(self.variant, |this, variant| this.with_variant(variant))
|
.when_some(self.variant, |this, variant| this.with_variant(variant))
|
||||||
.when_some(self.compact, |this, _| this.compact())
|
.when(self.compact, |this| this.compact())
|
||||||
|
.when(self.outline, |this| this.outline())
|
||||||
.on_click(move |_, _, _| {
|
.on_click(move |_, _, _| {
|
||||||
state.set(Some(child_index));
|
state.set(Some(child_index));
|
||||||
});
|
});
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue