theme: Add color `darken` function (#20746)

Danilo Leal created

This PR adds a `darken` function that allows to reduce the lightness of
a color by a certain factor. This popped up as I wanted to add hover
styles to tinted-colors buttons.

Release Notes:

- N/A

Change summary

crates/theme/src/theme.rs                      | 16 ++++++++++++++++
crates/ui/src/components/button/button_like.rs |  7 ++++++-
2 files changed, 22 insertions(+), 1 deletion(-)

Detailed changes

crates/theme/src/theme.rs 🔗

@@ -315,6 +315,22 @@ impl Theme {
     pub fn window_background_appearance(&self) -> WindowBackgroundAppearance {
         self.styles.window_background_appearance
     }
+
+    /// Darkens the color by reducing its lightness.
+    /// The resulting lightness is clamped to ensure it doesn't go below 0.0.
+    ///
+    /// The first value darkens light appearance mode, the second darkens appearance dark mode.
+    ///
+    /// Note: This is a tentative solution and may be replaced with a more robust color system.
+    pub fn darken(&self, color: Hsla, light_amount: f32, dark_amount: f32) -> Hsla {
+        let amount = match self.appearance {
+            Appearance::Light => light_amount,
+            Appearance::Dark => dark_amount,
+        };
+        let mut hsla = color;
+        hsla.l = (hsla.l - amount).max(0.0);
+        hsla
+    }
 }
 
 /// Compounds a color with an alpha value.

crates/ui/src/components/button/button_like.rs 🔗

@@ -202,7 +202,12 @@ impl ButtonStyle {
                     icon_color: Color::Default.color(cx),
                 }
             }
-            ButtonStyle::Tinted(tint) => tint.button_like_style(cx),
+            ButtonStyle::Tinted(tint) => {
+                let mut styles = tint.button_like_style(cx);
+                let theme = cx.theme();
+                styles.background = theme.darken(styles.background, 0.05, 0.2);
+                styles
+            }
             ButtonStyle::Subtle => ButtonLikeStyles {
                 background: cx.theme().colors().ghost_element_hover,
                 border_color: transparent_black(),