gradient_fade.rs

 1use gpui::{Hsla, Pixels, SharedString, linear_color_stop, linear_gradient, px};
 2
 3use crate::prelude::*;
 4
 5/// A gradient overlay that fades from a solid color to transparent.
 6#[derive(IntoElement)]
 7pub struct GradientFade {
 8    base_bg: Hsla,
 9    hover_bg: Hsla,
10    active_bg: Hsla,
11    width: Pixels,
12    right: Pixels,
13    gradient_stop: f32,
14    group_name: Option<SharedString>,
15}
16
17impl GradientFade {
18    pub fn new(base_bg: Hsla, hover_bg: Hsla, active_bg: Hsla) -> Self {
19        Self {
20            base_bg,
21            hover_bg,
22            active_bg,
23            width: px(48.0),
24            right: px(0.0),
25            gradient_stop: 0.6,
26            group_name: None,
27        }
28    }
29
30    pub fn width(mut self, width: Pixels) -> Self {
31        self.width = width;
32        self
33    }
34
35    pub fn right(mut self, right: Pixels) -> Self {
36        self.right = right;
37        self
38    }
39
40    pub fn gradient_stop(mut self, stop: f32) -> Self {
41        self.gradient_stop = stop;
42        self
43    }
44
45    pub fn group_name(mut self, name: impl Into<SharedString>) -> Self {
46        self.group_name = Some(name.into());
47        self
48    }
49}
50
51impl RenderOnce for GradientFade {
52    fn render(self, _window: &mut Window, cx: &mut App) -> impl IntoElement {
53        let stop = self.gradient_stop;
54
55        // Best-effort to flatten potentially-transparent colors to opaque ones.
56        let app_bg = cx.theme().colors().background;
57        let base_bg = app_bg.blend(self.base_bg);
58        let hover_bg = app_bg.blend(self.hover_bg);
59        let active_bg = app_bg.blend(self.active_bg);
60
61        div()
62            .id("gradient_fade")
63            .absolute()
64            .top_0()
65            .right(self.right)
66            .w(self.width)
67            .h_full()
68            .bg(linear_gradient(
69                90.,
70                linear_color_stop(base_bg, stop),
71                linear_color_stop(base_bg.opacity(0.0), 0.),
72            ))
73            .when_some(self.group_name.clone(), |element, group_name| {
74                element.group_hover(group_name, move |s| {
75                    s.bg(linear_gradient(
76                        90.,
77                        linear_color_stop(hover_bg, stop),
78                        linear_color_stop(hover_bg.opacity(0.0), 0.),
79                    ))
80                })
81            })
82            .when_some(self.group_name, |element, group_name| {
83                element.group_active(group_name, move |s| {
84                    s.bg(linear_gradient(
85                        90.,
86                        linear_color_stop(active_bg, stop),
87                        linear_color_stop(active_bg.opacity(0.0), 0.),
88                    ))
89                })
90            })
91    }
92}