1use std::marker::PhantomData;
2
3use gpui3::{rems, AbsoluteLength};
4
5use crate::prelude::*;
6use crate::{Icon, IconButton, Label, Panel, PanelSide};
7
8#[derive(Element)]
9pub struct AssistantPanel<S: 'static + Send + Sync + Clone> {
10 state_type: PhantomData<S>,
11 scroll_state: ScrollState,
12 current_side: PanelSide,
13}
14
15impl<S: 'static + Send + Sync + Clone> AssistantPanel<S> {
16 pub fn new() -> Self {
17 Self {
18 state_type: PhantomData,
19 scroll_state: ScrollState::default(),
20 current_side: PanelSide::default(),
21 }
22 }
23
24 pub fn side(mut self, side: PanelSide) -> Self {
25 self.current_side = side;
26 self
27 }
28
29 fn render(&mut self, cx: &mut ViewContext<S>) -> impl Element<State = S> {
30 let theme = theme(cx);
31
32 struct PanelPayload {
33 pub scroll_state: ScrollState,
34 }
35
36 Panel::new(
37 self.scroll_state.clone(),
38 |_, payload| {
39 let payload = payload.downcast_ref::<PanelPayload>().unwrap();
40
41 vec![div()
42 .flex()
43 .flex_col()
44 .h_full()
45 .px_2()
46 .gap_2()
47 // Header
48 .child(
49 div()
50 .flex()
51 .justify_between()
52 .gap_2()
53 .child(
54 div()
55 .flex()
56 .child(IconButton::new(Icon::Menu))
57 .child(Label::new("New Conversation")),
58 )
59 .child(
60 div()
61 .flex()
62 .items_center()
63 .gap_px()
64 .child(IconButton::new(Icon::SplitMessage))
65 .child(IconButton::new(Icon::Quote))
66 .child(IconButton::new(Icon::MagicWand))
67 .child(IconButton::new(Icon::Plus))
68 .child(IconButton::new(Icon::Maximize)),
69 ),
70 )
71 // Chat Body
72 .child(
73 div()
74 .w_full()
75 .flex()
76 .flex_col()
77 .gap_3()
78 .overflow_y_scroll(payload.scroll_state.clone())
79 .child(Label::new("Is this thing on?")),
80 )
81 .into_any()]
82 },
83 Box::new(PanelPayload {
84 scroll_state: self.scroll_state.clone(),
85 }),
86 )
87 .side(self.current_side)
88 .width(AbsoluteLength::Rems(rems(32.)))
89 }
90}
91
92#[cfg(feature = "stories")]
93pub use stories::*;
94
95#[cfg(feature = "stories")]
96mod stories {
97 use crate::Story;
98
99 use super::*;
100
101 #[derive(Element)]
102 pub struct AssistantPanelStory<S: 'static + Send + Sync + Clone> {
103 state_type: PhantomData<S>,
104 }
105
106 impl<S: 'static + Send + Sync + Clone> AssistantPanelStory<S> {
107 pub fn new() -> Self {
108 Self {
109 state_type: PhantomData,
110 }
111 }
112
113 fn render(&mut self, cx: &mut ViewContext<S>) -> impl Element<State = S> {
114 Story::container(cx)
115 .child(Story::title_for::<_, AssistantPanel<S>>(cx))
116 .child(Story::label(cx, "Default"))
117 .child(AssistantPanel::new())
118 }
119 }
120}