collab_panel.rs

  1use gpui3::{
  2    div, img, svg, view, AppContext, Context, Element, Interactive, IntoAnyElement, MouseButton,
  3    ParentElement, ScrollState, SharedString, StyleHelpers, Styled, View, ViewContext,
  4    WindowContext,
  5};
  6use ui::{theme, Theme};
  7
  8pub struct CollabPanel {
  9    scroll_state: ScrollState,
 10}
 11
 12pub fn collab_panel<S: 'static>(cx: &mut WindowContext) -> View<CollabPanel, S> {
 13    view(cx.entity(|cx| CollabPanel::new(cx)), CollabPanel::render)
 14}
 15
 16impl CollabPanel {
 17    fn new(_: &mut AppContext) -> Self {
 18        CollabPanel {
 19            scroll_state: ScrollState::default(),
 20        }
 21    }
 22}
 23
 24impl CollabPanel {
 25    fn render(&mut self, cx: &mut ViewContext<Self>) -> impl Element<State = Self> {
 26        let theme = theme(cx);
 27
 28        // Panel
 29        div()
 30            .w_64()
 31            .h_full()
 32            .flex()
 33            .flex_col()
 34            .font("Courier")
 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                            .on_click(MouseButton::Left, |_, _, _| {
 49                                dbg!("click!");
 50                            })
 51                            .fill(theme.lowest.base.default.background)
 52                            .pb_1()
 53                            .border_color(theme.lowest.base.default.border)
 54                            .border_b()
 55                            //:: https://tailwindcss.com/docs/hover-focus-and-other-states#styling-based-on-parent-state
 56                            // .group()
 57                            // List Section Header
 58                            .child(self.list_section_header("#CRDB 🗃️", true, &theme))
 59                            // List Item Large
 60                            .child(self.list_item(
 61                                "http://github.com/maxbrunsfeld.png?s=50",
 62                                "maxbrunsfeld",
 63                                &theme,
 64                            )),
 65                    )
 66                    .child(
 67                        div()
 68                            .py_2()
 69                            .flex()
 70                            .flex_col()
 71                            .child(self.list_section_header("CHANNELS", true, &theme)),
 72                    )
 73                    .child(
 74                        div()
 75                            .py_2()
 76                            .flex()
 77                            .flex_col()
 78                            .child(self.list_section_header("CONTACTS", true, &theme))
 79                            .children(
 80                                std::iter::repeat_with(|| {
 81                                    vec![
 82                                        self.list_item(
 83                                            "http://github.com/as-cii.png?s=50",
 84                                            "as-cii",
 85                                            &theme,
 86                                        ),
 87                                        self.list_item(
 88                                            "http://github.com/nathansobo.png?s=50",
 89                                            "nathansobo",
 90                                            &theme,
 91                                        ),
 92                                        self.list_item(
 93                                            "http://github.com/maxbrunsfeld.png?s=50",
 94                                            "maxbrunsfeld",
 95                                            &theme,
 96                                        ),
 97                                    ]
 98                                })
 99                                .take(5)
100                                .flatten(),
101                            ),
102                    ),
103            )
104            .child(
105                div()
106                    .h_7()
107                    .px_2()
108                    .border_t()
109                    .border_color(theme.middle.variant.default.border)
110                    .flex()
111                    .items_center()
112                    .child(
113                        div()
114                            .text_sm()
115                            .text_color(theme.middle.variant.default.foreground)
116                            .child("Find..."),
117                    ),
118            )
119    }
120
121    fn list_section_header(
122        &self,
123        label: impl IntoAnyElement<Self>,
124        expanded: bool,
125        theme: &Theme,
126    ) -> impl Element<State = Self> {
127        div()
128            .h_7()
129            .px_2()
130            .flex()
131            .justify_between()
132            .items_center()
133            .hover()
134            .fill(theme.lowest.base.active.background)
135            .child(div().flex().gap_1().text_sm().child(label))
136            .child(
137                div().flex().h_full().gap_1().items_center().child(
138                    svg()
139                        .path(if expanded {
140                            "icons/caret_down.svg"
141                        } else {
142                            "icons/caret_up.svg"
143                        })
144                        .w_3p5()
145                        .h_3p5()
146                        .fill(theme.middle.variant.default.foreground),
147                ),
148            )
149    }
150
151    fn list_item(
152        &self,
153        avatar_uri: impl Into<SharedString>,
154        label: impl IntoAnyElement<Self>,
155        theme: &Theme,
156    ) -> impl Element<State = Self> {
157        div()
158            .h_7()
159            .px_2()
160            .flex()
161            .items_center()
162            .hover()
163            .fill(theme.lowest.variant.hovered.background)
164            // .active()
165            // .fill(theme.lowest.variant.pressed.background)
166            .child(
167                div()
168                    .flex()
169                    .items_center()
170                    .gap_1()
171                    .text_sm()
172                    .child(
173                        img()
174                            .uri(avatar_uri)
175                            .size_3p5()
176                            .rounded_full()
177                            .fill(theme.middle.positive.default.foreground)
178                            .shadow_md(),
179                    )
180                    .child(label),
181            )
182    }
183}