diff --git a/crates/collab_ui2/src/collab_panel.rs b/crates/collab_ui2/src/collab_panel.rs index 45129fa790..c8119d2127 100644 --- a/crates/collab_ui2/src/collab_panel.rs +++ b/crates/collab_ui2/src/collab_panel.rs @@ -2110,6 +2110,47 @@ impl CollabPanel { None }; + let button_container = |cx: &mut ViewContext| { + h_stack() + .absolute() + // We're using a negative coordinate for the right anchor to + // counteract the padding of the `ListItem`. + // + // This prevents a gap from showing up between the background + // of this element and the edge of the collab panel. + .right(rems(-0.5)) + // HACK: Without this the channel name clips on top of the icons, but I'm not sure why. + .z_index(10) + .bg(cx.theme().colors().panel_background) + .when(is_selected || is_active, |this| { + this.bg(cx.theme().colors().ghost_element_selected) + }) + }; + + let messages_button = |cx: &mut ViewContext| { + IconButton::new("channel_chat", Icon::MessageBubbles) + .icon_size(IconSize::Small) + .icon_color(if has_messages_notification { + Color::Default + } else { + Color::Muted + }) + .on_click(cx.listener(move |this, _, cx| this.join_channel_chat(channel_id, cx))) + .tooltip(|cx| Tooltip::text("Open channel chat", cx)) + }; + + let notes_button = |cx: &mut ViewContext| { + IconButton::new("channel_notes", Icon::File) + .icon_size(IconSize::Small) + .icon_color(if has_notes_notification { + Color::Default + } else { + Color::Muted + }) + .on_click(cx.listener(move |this, _, cx| this.open_channel_notes(channel_id, cx))) + .tooltip(|cx| Tooltip::text("Open channel notes", cx)) + }; + let width = self.width.unwrap_or(px(240.)); div() @@ -2172,63 +2213,49 @@ impl CollabPanel { .child(Label::new(channel.name.clone())) .children(face_pile.map(|face_pile| face_pile.render(cx))), ) - .end_slot( - h_stack() - .absolute() - // We're using a negative coordinate for the right anchor to - // counteract the padding of the `ListItem`. - // - // This prevents a gap from showing up between the background - // of this element and the edge of the collab panel. - .right(rems(-0.5)) - // HACK: Without this the channel name clips on top of the icons, but I'm not sure why. - .z_index(10) - .bg(cx.theme().colors().panel_background) - .when(is_selected || is_active, |this| { - this.bg(cx.theme().colors().ghost_element_selected) - }) - .child( - h_stack() - .px_1() - // The element hover background has a slight transparency to it, so we - // need to apply it to the inner element so that it blends with the solid - // background color of the absolutely-positioned element. - .group_hover("", |style| { - style.bg(cx.theme().colors().ghost_element_hover) - }) - .child( - IconButton::new("channel_chat", Icon::MessageBubbles) - .icon_size(IconSize::Small) - .icon_color(if has_messages_notification { - Color::Default - } else { - Color::Muted - }) - .when(!has_messages_notification, |this| { - this.visible_on_hover("") - }) - .on_click(cx.listener(move |this, _, cx| { - this.join_channel_chat(channel_id, cx) - })) - .tooltip(|cx| Tooltip::text("Open channel chat", cx)), - ) - .child( - IconButton::new("channel_notes", Icon::File) - .icon_size(IconSize::Small) - .icon_color(if has_notes_notification { - Color::Default - } else { - Color::Muted - }) - .when(!has_notes_notification, |this| { - this.visible_on_hover("") - }) - .on_click(cx.listener(move |this, _, cx| { - this.open_channel_notes(channel_id, cx) - })) - .tooltip(|cx| Tooltip::text("Open channel notes", cx)), - ), - ), + .end_slot::
( + // If we have a notification for either button, we want to show the corresponding + // button(s) as indicators. + if has_messages_notification || has_notes_notification { + Some( + button_container(cx).child( + h_stack() + .px_1() + .children( + // We only want to render the messages button if there are unseen messages. + // This way we don't take up any space that might overlap the channel name + // when there are no notifications. + has_messages_notification.then(|| messages_button(cx)), + ) + .child( + // We always want the notes button to take up space to prevent layout + // shift when hovering over the channel. + // However, if there are is no notes notification we just show an empty slot. + notes_button(cx) + .when(!has_notes_notification, |this| { + this.visible_on_hover("") + }), + ), + ), + ) + } else { + None + }, + ) + .end_hover_slot( + // When we hover the channel entry we want to always show both buttons. + button_container(cx).child( + h_stack() + .px_1() + // The element hover background has a slight transparency to it, so we + // need to apply it to the inner element so that it blends with the solid + // background color of the absolutely-positioned element. + .group_hover("", |style| { + style.bg(cx.theme().colors().ghost_element_hover) + }) + .child(messages_button(cx)) + .child(notes_button(cx)), + ), ), ) .tooltip(|cx| Tooltip::text("Join channel", cx))