1use std::marker::PhantomData;
2
3use gpui2::geometry::rems;
4
5use crate::prelude::*;
6use crate::theme::theme;
7use crate::{Icon, IconButton, Label, Panel, PanelSide};
8
9#[derive(Element)]
10pub struct AssistantPanel<V: 'static> {
11 view_type: PhantomData<V>,
12 scroll_state: ScrollState,
13 current_side: PanelSide,
14}
15
16impl<V: 'static> AssistantPanel<V> {
17 pub fn new() -> Self {
18 Self {
19 view_type: PhantomData,
20 scroll_state: ScrollState::default(),
21 current_side: PanelSide::default(),
22 }
23 }
24
25 pub fn side(mut self, side: PanelSide) -> Self {
26 self.current_side = side;
27 self
28 }
29
30 fn render(&mut self, _: &mut V, cx: &mut ViewContext<V>) -> impl IntoElement<V> {
31 let theme = theme(cx);
32
33 struct PanelPayload {
34 pub scroll_state: ScrollState,
35 }
36
37 Panel::new(
38 self.scroll_state.clone(),
39 |_, payload| {
40 let payload = payload.downcast_ref::<PanelPayload>().unwrap();
41
42 vec![div()
43 .flex()
44 .flex_col()
45 .h_full()
46 .px_2()
47 .gap_2()
48 // Header
49 .child(
50 div()
51 .flex()
52 .justify_between()
53 .gap_2()
54 .child(
55 div()
56 .flex()
57 .child(IconButton::new(Icon::Menu))
58 .child(Label::new("New Conversation")),
59 )
60 .child(
61 div()
62 .flex()
63 .items_center()
64 .gap_px()
65 .child(IconButton::new(Icon::SplitMessage))
66 .child(IconButton::new(Icon::Quote))
67 .child(IconButton::new(Icon::MagicWand))
68 .child(IconButton::new(Icon::Plus))
69 .child(IconButton::new(Icon::Maximize)),
70 ),
71 )
72 // Chat Body
73 .child(
74 div()
75 .w_full()
76 .flex()
77 .flex_col()
78 .gap_3()
79 .overflow_y_scroll(payload.scroll_state.clone())
80 .child(Label::new("Is this thing on?")),
81 )
82 .into_any()]
83 },
84 Box::new(PanelPayload {
85 scroll_state: self.scroll_state.clone(),
86 }),
87 )
88 .side(self.current_side)
89 .width(rems(32.))
90 }
91}