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}