From 2a331fcb79344e22cb6caa6296d3049b6b142b5b Mon Sep 17 00:00:00 2001 From: Jason Lee Date: Tue, 24 Sep 2024 10:52:01 +0800 Subject: [PATCH] theme: Add `shadow` option to support toggle shadow for base controls, default: true. (#268) - Add shadow to Button if it enabled. --- crates/story/src/button_story.rs | 13 ++++++++++++- crates/ui/src/button.rs | 29 +++++++++++++++++++++++++++++ crates/ui/src/dropdown.rs | 2 +- crates/ui/src/input/input.rs | 2 +- crates/ui/src/input/otp_input.rs | 2 +- crates/ui/src/slider.rs | 9 +++++---- crates/ui/src/theme.rs | 7 +++++-- crates/ui/src/time/date_picker.rs | 2 +- 8 files changed, 55 insertions(+), 11 deletions(-) diff --git a/crates/story/src/button_story.rs b/crates/story/src/button_story.rs index 9df8fc9e..03689a54 100644 --- a/crates/story/src/button_story.rs +++ b/crates/story/src/button_story.rs @@ -9,7 +9,7 @@ use ui::{ checkbox::Checkbox, h_flex, prelude::FluentBuilder, - theme::ActiveTheme, + theme::{ActiveTheme, Theme}, v_flex, Disableable as _, Icon, IconName, Selectable as _, Sizable as _, }; @@ -114,6 +114,17 @@ impl Render for ButtonStory { view.compact = !view.compact; cx.notify(); })), + ) + .child( + Checkbox::new("shadow-button") + .label("Shadow") + .checked(cx.theme().shadow) + .on_click(cx.listener(|_, _, cx| { + let mut theme = cx.theme().clone(); + theme.shadow = !theme.shadow; + cx.set_global::(theme); + cx.refresh(); + })), ), ) .child( diff --git a/crates/ui/src/button.rs b/crates/ui/src/button.rs index 1da7b6d9..22d3b7b6 100644 --- a/crates/ui/src/button.rs +++ b/crates/ui/src/button.rs @@ -30,6 +30,7 @@ pub struct ButtonCustomStyle { color: Hsla, foreground: Hsla, border: Hsla, + shadow: bool, hover: Hsla, active: Hsla, } @@ -81,6 +82,7 @@ impl ButtonCustomStyle { border: cx.theme().border, hover: cx.theme().secondary_hover, active: cx.theme().secondary_active, + shadow: true, } } @@ -108,6 +110,11 @@ impl ButtonCustomStyle { self.active = color; self } + + pub fn shadow(mut self, shadow: bool) -> Self { + self.shadow = shadow; + self + } } #[derive(Clone, Copy, PartialEq, Eq)] @@ -318,6 +325,9 @@ impl RenderOnce for Button { .justify_center() .cursor_pointer() .overflow_hidden() + .when(cx.theme().shadow && normal_style.shadow, |this| { + this.shadow_sm() + }) .when(!style.no_padding(), |this| { if self.label.is_none() && self.children.is_empty() { // Icon Button @@ -450,6 +460,7 @@ struct ButtonStyles { border: Hsla, fg: Hsla, underline: bool, + shadow: bool, } impl ButtonStyle { @@ -496,17 +507,27 @@ impl ButtonStyle { } } + fn shadow(&self, _: &WindowContext) -> bool { + match self { + ButtonStyle::Primary | ButtonStyle::Secondary | ButtonStyle::Danger => true, + ButtonStyle::Custom(c) => c.shadow, + _ => false, + } + } + fn normal(&self, cx: &WindowContext) -> ButtonStyles { let bg = self.bg_color(cx); let border = self.border_color(cx); let fg = self.text_color(cx); let underline = self.underline(cx); + let shadow = self.shadow(cx); ButtonStyles { bg, border, fg, underline, + shadow, } } @@ -526,12 +547,14 @@ impl ButtonStyle { _ => self.text_color(cx), }; let underline = self.underline(cx); + let shadow = self.shadow(cx); ButtonStyles { bg, border, fg, underline, + shadow, } } @@ -553,12 +576,14 @@ impl ButtonStyle { _ => self.text_color(cx), }; let underline = self.underline(cx); + let shadow = self.shadow(cx); ButtonStyles { bg, border, fg, underline, + shadow, } } @@ -580,12 +605,14 @@ impl ButtonStyle { _ => self.text_color(cx), }; let underline = self.underline(cx); + let shadow = self.shadow(cx); ButtonStyles { bg, border, fg, underline, + shadow, } } @@ -606,12 +633,14 @@ impl ButtonStyle { let border = bg; let underline = self.underline(cx); + let shadow = self.shadow(cx); ButtonStyles { bg, border, fg, underline, + shadow, } } } diff --git a/crates/ui/src/dropdown.rs b/crates/ui/src/dropdown.rs index f68687ef..ca1dd185 100644 --- a/crates/ui/src/dropdown.rs +++ b/crates/ui/src/dropdown.rs @@ -605,7 +605,7 @@ where .border_1() .border_color(cx.theme().input) .rounded(px(cx.theme().radius)) - .shadow_sm() + .when(cx.theme().shadow, |this| this.shadow_sm()) .map(|this| { if self.disabled { this.cursor_not_allowed() diff --git a/crates/ui/src/input/input.rs b/crates/ui/src/input/input.rs index 08dbb778..f95291d8 100644 --- a/crates/ui/src/input/input.rs +++ b/crates/ui/src/input/input.rs @@ -1126,7 +1126,7 @@ impl Render for TextInput { .border_color(cx.theme().input) .border_1() .rounded(px(cx.theme().radius)) - .shadow_sm() + .when(cx.theme().shadow, |this| this.shadow_sm()) .when(focused, |this| this.outline(cx)) .when(prefix.is_none(), |this| this.input_pl(self.size)) .when(suffix.is_none(), |this| this.input_pr(self.size)) diff --git a/crates/ui/src/input/otp_input.rs b/crates/ui/src/input/otp_input.rs index 5c4559e2..41b3fdf9 100644 --- a/crates/ui/src/input/otp_input.rs +++ b/crates/ui/src/input/otp_input.rs @@ -212,7 +212,7 @@ impl Render for OtpInput { .border_color(cx.theme().input) .bg(cx.theme().background) .when(is_input_focused, |this| this.border_color(cx.theme().ring)) - .shadow_sm() + .when(cx.theme().shadow, |this| this.shadow_sm()) .items_center() .justify_center() .rounded_md() diff --git a/crates/ui/src/slider.rs b/crates/ui/src/slider.rs index abc355b5..ce6dbb5d 100644 --- a/crates/ui/src/slider.rs +++ b/crates/ui/src/slider.rs @@ -1,8 +1,9 @@ use crate::{theme::ActiveTheme, tooltip::Tooltip}; use gpui::{ - canvas, div, px, relative, Axis, Bounds, DragMoveEvent, EntityId, EventEmitter, - InteractiveElement, IntoElement, MouseButton, MouseDownEvent, ParentElement as _, Pixels, - Point, Render, StatefulInteractiveElement as _, Styled, ViewContext, VisualContext as _, + canvas, div, prelude::FluentBuilder as _, px, relative, Axis, Bounds, DragMoveEvent, EntityId, + EventEmitter, InteractiveElement, IntoElement, MouseButton, MouseDownEvent, ParentElement as _, + Pixels, Point, Render, StatefulInteractiveElement as _, Styled, ViewContext, + VisualContext as _, }; #[derive(Clone, Render)] @@ -142,7 +143,7 @@ impl Slider { .rounded_full() .border_1() .border_color(cx.theme().slider_bar.opacity(0.9)) - .shadow_md() + .when(cx.theme().shadow, |this| this.shadow_md()) .bg(cx.theme().slider_thumb) .tooltip(move |cx| Tooltip::new(format!("{}", value), cx)) } diff --git a/crates/ui/src/theme.rs b/crates/ui/src/theme.rs index 08fbf1fd..7a82ea8a 100644 --- a/crates/ui/src/theme.rs +++ b/crates/ui/src/theme.rs @@ -257,7 +257,7 @@ impl Colors { } } -#[derive(Debug)] +#[derive(Debug, Clone)] pub struct Theme { pub mode: ThemeMode, pub transparent: Hsla, @@ -290,6 +290,8 @@ pub struct Theme { pub border: Hsla, pub input: Hsla, pub ring: Hsla, + /// Set to true to enable shadow for Button, Input, Dropdown, DatePicker ... + pub shadow: bool, pub selection: Hsla, pub scrollbar: Hsla, pub scrollbar_thumb: Hsla, @@ -343,6 +345,7 @@ impl From for Theme { "FreeMono".into() }, radius: 4.0, + shadow: true, title_bar_background: colors.title_bar_background, background: colors.background, foreground: colors.foreground, @@ -401,7 +404,7 @@ impl From for Theme { } } -#[derive(Debug, Default, PartialEq, PartialOrd, Eq)] +#[derive(Debug, Clone, Copy, Default, PartialEq, PartialOrd, Eq)] pub enum ThemeMode { Light, #[default] diff --git a/crates/ui/src/time/date_picker.rs b/crates/ui/src/time/date_picker.rs index 60b94054..f7d74a66 100644 --- a/crates/ui/src/time/date_picker.rs +++ b/crates/ui/src/time/date_picker.rs @@ -216,7 +216,7 @@ impl Render for DatePicker { .border_1() .border_color(cx.theme().input) .rounded(px(cx.theme().radius)) - .shadow_sm() + .when(cx.theme().shadow, |this| this.shadow_sm()) .cursor_pointer() .overflow_hidden() .input_text_size(self.size)