parallel_agents_illustration.rs

  1use crate::{DiffStat, Divider, prelude::*};
  2use gpui::{Animation, AnimationExt, pulsating_between};
  3use std::time::Duration;
  4
  5#[derive(IntoElement)]
  6pub struct ParallelAgentsIllustration;
  7
  8impl ParallelAgentsIllustration {
  9    pub fn new() -> Self {
 10        Self
 11    }
 12}
 13
 14impl RenderOnce for ParallelAgentsIllustration {
 15    fn render(self, _window: &mut Window, cx: &mut App) -> impl IntoElement {
 16        let icon_container = || h_flex().size_4().flex_shrink_0().justify_center();
 17
 18        let title_bar = |id: &'static str, width: DefiniteLength, duration_ms: u64| {
 19            div()
 20                .h_2()
 21                .w(width)
 22                .rounded_full()
 23                .debug_bg_blue()
 24                .bg(cx.theme().colors().element_selected)
 25                .with_animation(
 26                    id,
 27                    Animation::new(Duration::from_millis(duration_ms))
 28                        .repeat()
 29                        .with_easing(pulsating_between(0.4, 0.8)),
 30                    |label, delta| label.opacity(delta),
 31                )
 32        };
 33
 34        let time =
 35            |time: SharedString| Label::new(time).size(LabelSize::XSmall).color(Color::Muted);
 36
 37        let worktree = |worktree: SharedString| {
 38            h_flex()
 39                .gap_1()
 40                .child(
 41                    Icon::new(IconName::GitWorktree)
 42                        .color(Color::Muted)
 43                        .size(IconSize::XSmall),
 44                )
 45                .child(
 46                    Label::new(worktree)
 47                        .size(LabelSize::XSmall)
 48                        .color(Color::Muted),
 49                )
 50        };
 51
 52        let dot_separator = || {
 53            Label::new("")
 54                .size(LabelSize::Small)
 55                .color(Color::Muted)
 56                .alpha(0.5)
 57        };
 58
 59        let agent = |id: &'static str,
 60                     icon: IconName,
 61                     width: DefiniteLength,
 62                     duration_ms: u64,
 63                     data: Vec<AnyElement>| {
 64            v_flex()
 65                .p_2()
 66                .child(
 67                    h_flex()
 68                        .w_full()
 69                        .gap_2()
 70                        .child(
 71                            icon_container()
 72                                .child(Icon::new(icon).size(IconSize::Small).color(Color::Muted)),
 73                        )
 74                        .child(title_bar(id, width, duration_ms)),
 75                )
 76                .child(
 77                    h_flex()
 78                        .opacity(0.8)
 79                        .w_full()
 80                        .gap_2()
 81                        .child(icon_container())
 82                        .children(data),
 83                )
 84        };
 85
 86        let agents = v_flex()
 87            .absolute()
 88            .w(rems_from_px(380.))
 89            .top_8()
 90            .rounded_t_sm()
 91            .border_1()
 92            .border_color(cx.theme().colors().border.opacity(0.5))
 93            .bg(cx.theme().colors().elevated_surface_background)
 94            .shadow_md()
 95            .child(agent(
 96                "zed-agent-bar",
 97                IconName::ZedAgent,
 98                relative(0.7),
 99                1800,
100                vec![
101                    worktree("happy-tree".into()).into_any_element(),
102                    dot_separator().into_any_element(),
103                    DiffStat::new("ds", 23, 13)
104                        .label_size(LabelSize::XSmall)
105                        .into_any_element(),
106                    dot_separator().into_any_element(),
107                    time("2m".into()).into_any_element(),
108                ],
109            ))
110            .child(Divider::horizontal())
111            .child(agent(
112                "claude-bar",
113                IconName::AiClaude,
114                relative(0.85),
115                2400,
116                vec![
117                    DiffStat::new("ds", 120, 84)
118                        .label_size(LabelSize::XSmall)
119                        .into_any_element(),
120                    dot_separator().into_any_element(),
121                    time("16m".into()).into_any_element(),
122                ],
123            ))
124            .child(Divider::horizontal())
125            .child(agent(
126                "openai-bar",
127                IconName::AiOpenAi,
128                relative(0.4),
129                3100,
130                vec![
131                    worktree("silent-forest".into()).into_any_element(),
132                    dot_separator().into_any_element(),
133                    time("37m".into()).into_any_element(),
134                ],
135            ))
136            .child(Divider::horizontal());
137
138        h_flex()
139            .relative()
140            .h(rems_from_px(180.))
141            .bg(cx.theme().colors().editor_background)
142            .justify_center()
143            .items_end()
144            .rounded_t_md()
145            .overflow_hidden()
146            .bg(gpui::black().opacity(0.2))
147            .child(agents)
148    }
149}