1use crate::theme::{theme, Theme};
2use gpui2::{
3 elements::{div, div::ScrollState, img, svg},
4 style::{StyleHelpers, Styleable},
5 ArcCow, Element, IntoElement, ParentElement, ViewContext,
6};
7use std::marker::PhantomData;
8
9#[derive(Element)]
10pub struct CollabPanelElement<V: 'static> {
11 view_type: PhantomData<V>,
12 scroll_state: ScrollState,
13}
14
15// When I improve child view rendering, I'd like to have V implement a trait that
16// provides the scroll state, among other things.
17pub fn collab_panel<V: 'static>(scroll_state: ScrollState) -> CollabPanelElement<V> {
18 CollabPanelElement {
19 view_type: PhantomData,
20 scroll_state,
21 }
22}
23
24impl<V: 'static> CollabPanelElement<V> {
25 fn render(&mut self, _: &mut V, cx: &mut ViewContext<V>) -> impl IntoElement<V> {
26 let theme = theme(cx);
27
28 // Panel
29 div()
30 .w_64()
31 .h_full()
32 .flex()
33 .flex_col()
34 .font("Zed Sans Extended")
35 .text_color(theme.middle.base.default.foreground)
36 .border_color(theme.middle.base.default.border)
37 .border()
38 .fill(theme.middle.base.default.background)
39 .child(
40 div()
41 .w_full()
42 .flex()
43 .flex_col()
44 .overflow_y_scroll(self.scroll_state.clone())
45 // List Container
46 .child(
47 div()
48 .fill(theme.lowest.base.default.background)
49 .pb_1()
50 .border_color(theme.lowest.base.default.border)
51 .border_b()
52 //:: https://tailwindcss.com/docs/hover-focus-and-other-states#styling-based-on-parent-state
53 // .group()
54 // List Section Header
55 .child(self.list_section_header("#CRDB", true, &theme))
56 // List Item Large
57 .child(self.list_item(
58 "http://github.com/maxbrunsfeld.png?s=50",
59 "maxbrunsfeld",
60 &theme,
61 )),
62 )
63 .child(
64 div()
65 .py_2()
66 .flex()
67 .flex_col()
68 .child(self.list_section_header("CHANNELS", true, &theme)),
69 )
70 .child(
71 div()
72 .py_2()
73 .flex()
74 .flex_col()
75 .child(self.list_section_header("CONTACTS", true, &theme))
76 .children(
77 std::iter::repeat_with(|| {
78 vec![
79 self.list_item(
80 "http://github.com/as-cii.png?s=50",
81 "as-cii",
82 &theme,
83 ),
84 self.list_item(
85 "http://github.com/nathansobo.png?s=50",
86 "nathansobo",
87 &theme,
88 ),
89 self.list_item(
90 "http://github.com/maxbrunsfeld.png?s=50",
91 "maxbrunsfeld",
92 &theme,
93 ),
94 ]
95 })
96 .take(3)
97 .flatten(),
98 ),
99 ),
100 )
101 .child(
102 div()
103 .h_7()
104 .px_2()
105 .border_t()
106 .border_color(theme.middle.variant.default.border)
107 .flex()
108 .items_center()
109 .child(
110 div()
111 .text_sm()
112 .text_color(theme.middle.variant.default.foreground)
113 .child("Find..."),
114 ),
115 )
116 }
117
118 fn list_section_header(
119 &self,
120 label: impl Into<ArcCow<'static, str>>,
121 expanded: bool,
122 theme: &Theme,
123 ) -> impl Element<V> {
124 div()
125 .h_7()
126 .px_2()
127 .flex()
128 .justify_between()
129 .items_center()
130 .child(div().flex().gap_1().text_sm().child(label))
131 .child(
132 div().flex().h_full().gap_1().items_center().child(
133 svg()
134 .path(if expanded {
135 "icons/caret_down.svg"
136 } else {
137 "icons/caret_up.svg"
138 })
139 .w_3p5()
140 .h_3p5()
141 .fill(theme.middle.variant.default.foreground),
142 ),
143 )
144 }
145
146 fn list_item(
147 &self,
148 avatar_uri: impl Into<ArcCow<'static, str>>,
149 label: impl Into<ArcCow<'static, str>>,
150 theme: &Theme,
151 ) -> impl Element<V> {
152 div()
153 .h_7()
154 .px_2()
155 .flex()
156 .items_center()
157 .hover()
158 .fill(theme.lowest.variant.hovered.background)
159 .active()
160 .fill(theme.lowest.variant.pressed.background)
161 .child(
162 div()
163 .flex()
164 .items_center()
165 .gap_1()
166 .text_sm()
167 .child(
168 img()
169 .uri(avatar_uri)
170 .size_3p5()
171 .rounded_full()
172 .fill(theme.middle.positive.default.foreground),
173 )
174 .child(label),
175 )
176 }
177}