Tidy up indicators in collab panel (#8214)

Conrad Irwin , Marshall , and Marshall Bowers created

Move away from columns of icons towards the "changed" info dot we used
for files.

Secondary actions for chat/notes still show up (if you're lucky) on
hover.

Co-Authored-By: Marshall <marshall@zed.dev>



Release Notes:

- Improved design of collab panel

---------

Co-authored-by: Marshall <marshall@zed.dev>
Co-authored-by: Marshall Bowers <elliott.codes@gmail.com>

Change summary

crates/collab_ui/src/collab_panel.rs | 78 +++++++++++++++++++++++------
script/bootstrap                     |  8 +-
2 files changed, 64 insertions(+), 22 deletions(-)

Detailed changes

crates/collab_ui/src/collab_panel.rs 🔗

@@ -34,7 +34,7 @@ use std::{mem, sync::Arc};
 use theme::{ActiveTheme, ThemeSettings};
 use ui::{
     prelude::*, tooltip_container, Avatar, AvatarAvailabilityIndicator, Button, Color, ContextMenu,
-    Icon, IconButton, IconName, IconSize, Label, ListHeader, ListItem, Tooltip,
+    Icon, IconButton, IconName, IconSize, Indicator, Label, ListHeader, ListItem, Tooltip,
 };
 use util::{maybe, ResultExt, TryFutureExt};
 use workspace::{
@@ -963,6 +963,8 @@ impl CollabPanel {
         is_selected: bool,
         cx: &mut ViewContext<Self>,
     ) -> impl IntoElement {
+        let channel_store = self.channel_store.read(cx);
+        let has_channel_buffer_changed = channel_store.has_channel_buffer_changed(channel_id);
         ListItem::new("channel-notes")
             .selected(is_selected)
             .on_click(cx.listener(move |this, _, cx| {
@@ -970,9 +972,19 @@ impl CollabPanel {
             }))
             .start_slot(
                 h_flex()
+                    .relative()
                     .gap_1()
                     .child(render_tree_branch(false, true, cx))
-                    .child(IconButton::new(0, IconName::File)),
+                    .child(IconButton::new(0, IconName::File))
+                    .children(has_channel_buffer_changed.then(|| {
+                        div()
+                            .w_1p5()
+                            .z_index(1)
+                            .absolute()
+                            .right(px(2.))
+                            .top(px(2.))
+                            .child(Indicator::dot().color(Color::Info))
+                    })),
             )
             .child(Label::new("notes"))
             .tooltip(move |cx| Tooltip::text("Open Channel Notes", cx))
@@ -984,6 +996,8 @@ impl CollabPanel {
         is_selected: bool,
         cx: &mut ViewContext<Self>,
     ) -> impl IntoElement {
+        let channel_store = self.channel_store.read(cx);
+        let has_messages_notification = channel_store.has_new_messages(channel_id);
         ListItem::new("channel-chat")
             .selected(is_selected)
             .on_click(cx.listener(move |this, _, cx| {
@@ -991,9 +1005,19 @@ impl CollabPanel {
             }))
             .start_slot(
                 h_flex()
+                    .relative()
                     .gap_1()
                     .child(render_tree_branch(false, false, cx))
-                    .child(IconButton::new(0, IconName::MessageBubbles)),
+                    .child(IconButton::new(0, IconName::MessageBubbles))
+                    .children(has_messages_notification.then(|| {
+                        div()
+                            .w_1p5()
+                            .z_index(1)
+                            .absolute()
+                            .right(px(2.))
+                            .top(px(4.))
+                            .child(Indicator::dot().color(Color::Info))
+                    })),
             )
             .child(Label::new("chat"))
             .tooltip(move |cx| Tooltip::text("Open Chat", cx))
@@ -2525,13 +2549,26 @@ impl CollabPanel {
                         },
                     ))
                     .start_slot(
-                        Icon::new(if is_public {
-                            IconName::Public
-                        } else {
-                            IconName::Hash
-                        })
-                        .size(IconSize::Small)
-                        .color(Color::Muted),
+                        div()
+                            .relative()
+                            .child(
+                                Icon::new(if is_public {
+                                    IconName::Public
+                                } else {
+                                    IconName::Hash
+                                })
+                                .size(IconSize::Small)
+                                .color(Color::Muted),
+                            )
+                            .children(has_notes_notification.then(|| {
+                                div()
+                                    .w_1p5()
+                                    .z_index(1)
+                                    .absolute()
+                                    .right(px(-1.))
+                                    .top(px(-1.))
+                                    .child(Indicator::dot().color(Color::Info))
+                            })),
                     )
                     .child(
                         h_flex()
@@ -2565,9 +2602,7 @@ impl CollabPanel {
                                         this.join_channel_chat(channel_id, cx)
                                     }))
                                     .tooltip(|cx| Tooltip::text("Open channel chat", cx))
-                                    .when(!has_messages_notification, |this| {
-                                        this.visible_on_hover("")
-                                    }),
+                                    .visible_on_hover(""),
                             )
                             .child(
                                 IconButton::new("channel_notes", IconName::File)
@@ -2583,9 +2618,7 @@ impl CollabPanel {
                                         this.open_channel_notes(channel_id, cx)
                                     }))
                                     .tooltip(|cx| Tooltip::text("Open channel notes", cx))
-                                    .when(!has_notes_notification, |this| {
-                                        this.visible_on_hover("")
-                                    }),
+                                    .visible_on_hover(""),
                             ),
                     ),
             )
@@ -2595,6 +2628,7 @@ impl CollabPanel {
                     cx.new_view(|_| JoinChannelTooltip {
                         channel_store: channel_store.clone(),
                         channel_id,
+                        has_notes_notification,
                     })
                     .into()
                 }
@@ -2880,17 +2914,25 @@ impl Render for DraggedChannelView {
 struct JoinChannelTooltip {
     channel_store: Model<ChannelStore>,
     channel_id: ChannelId,
+    has_notes_notification: bool,
 }
 
 impl Render for JoinChannelTooltip {
     fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
-        tooltip_container(cx, |div, cx| {
+        tooltip_container(cx, |container, cx| {
             let participants = self
                 .channel_store
                 .read(cx)
                 .channel_participants(self.channel_id);
 
-            div.child(Label::new("Join Channel"))
+            container
+                .child(Label::new("Join channel"))
+                .children(self.has_notes_notification.then(|| {
+                    h_flex()
+                        .gap_2()
+                        .child(Indicator::dot().color(Color::Info))
+                        .child(Label::new("Unread notes"))
+                }))
                 .children(participants.iter().map(|participant| {
                     h_flex()
                         .gap_2()

script/bootstrap 🔗

@@ -10,11 +10,11 @@ mkdir -p .blob_store/the-extensions-bucket
 echo "creating database..."
 script/sqlx database create
 
-echo "migrating database..."
-(cd crates/collab && cargo run -- migrate)
+# echo "migrating database..."
+# cargo run -p collab -- migrate
 
 echo "seeding database..."
 script/seed-db
 
-echo "Linux dependencies..."
-script/linux
+# echo "Linux dependencies..."
+# script/linux