Style collab panel (#3638)

This PR styles the collab panel.

Release Notes:

- N/A

---------

Co-authored-by: Nate Butler <iamnbutler@gmail.com>
Co-authored-by: Marshall Bowers <1486634+maxdeviant@users.noreply.github.com>
This commit is contained in:
Marshall Bowers 2023-12-13 18:20:04 -05:00 committed by GitHub
parent 1ad1cc1148
commit d59de96921
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 167 additions and 136 deletions

View file

@ -176,11 +176,11 @@ use feature_flags::{ChannelsAlpha, FeatureFlagAppExt, FeatureFlagViewExt};
use fuzzy::{match_strings, StringMatchCandidate};
use gpui::{
actions, canvas, div, img, impl_actions, overlay, point, prelude::*, px, rems, serde_json,
size, Action, AppContext, AsyncWindowContext, Bounds, ClipboardItem, DismissEvent, Div,
EventEmitter, FocusHandle, Focusable, FocusableView, Hsla, InteractiveElement, IntoElement,
Length, Model, MouseDownEvent, ParentElement, Pixels, Point, PromptLevel, Quad, Render,
RenderOnce, ScrollHandle, SharedString, Size, Stateful, Styled, Subscription, Task, View,
ViewContext, VisualContext, WeakView,
size, Action, AnyElement, AppContext, AsyncWindowContext, Bounds, ClipboardItem, DismissEvent,
Div, EventEmitter, FocusHandle, Focusable, FocusableView, Hsla, InteractiveElement,
IntoElement, Length, Model, MouseDownEvent, ParentElement, Pixels, Point, PromptLevel, Quad,
Render, RenderOnce, ScrollHandle, SharedString, Size, Stateful, Styled, Subscription, Task,
View, ViewContext, VisualContext, WeakView,
};
use project::{Fs, Project};
use serde_derive::{Deserialize, Serialize};
@ -402,7 +402,7 @@ impl CollabPanel {
let filter_editor = cx.build_view(|cx| {
let mut editor = Editor::single_line(cx);
editor.set_placeholder_text("Filter channels, contacts", cx);
editor.set_placeholder_text("Filter...", cx);
editor
});
@ -1157,24 +1157,20 @@ impl CollabPanel {
ListItem::new(SharedString::from(user.github_login.clone()))
.start_slot(Avatar::new(user.avatar_uri.clone()))
.child(
h_stack()
.w_full()
.justify_between()
.child(Label::new(user.github_login.clone()))
.child(if is_pending {
Label::new("Calling").color(Color::Muted).into_any_element()
} else if is_current_user {
IconButton::new("leave-call", Icon::ArrowRight)
.on_click(cx.listener(move |this, _, cx| {
Self::leave_call(cx);
}))
.tooltip(|cx| Tooltip::text("Leave Call", cx))
.into_any_element()
} else {
div().into_any_element()
}),
)
.child(Label::new(user.github_login.clone()))
.end_slot(if is_pending {
Label::new("Calling").color(Color::Muted).into_any_element()
} else if is_current_user {
IconButton::new("leave-call", Icon::Exit)
.style(ButtonStyle::Subtle)
.on_click(cx.listener(move |this, _, cx| {
Self::leave_call(cx);
}))
.tooltip(|cx| Tooltip::text("Leave Call", cx))
.into_any_element()
} else {
div().into_any_element()
})
.when_some(peer_id, |this, peer_id| {
this.tooltip(move |cx| Tooltip::text(tooltip.clone(), cx))
.on_click(cx.listener(move |this, _, cx| {
@ -1212,8 +1208,12 @@ impl CollabPanel {
.detach_and_log_err(cx);
});
}))
.start_slot(render_tree_branch(is_last, cx))
.child(IconButton::new(0, Icon::Folder))
.start_slot(
h_stack()
.gap_1()
.child(render_tree_branch(is_last, cx))
.child(IconButton::new(0, Icon::Folder)),
)
.child(Label::new(project_name.clone()))
.tooltip(move |cx| Tooltip::text(format!("Open {}", project_name), cx))
@ -1305,8 +1305,12 @@ impl CollabPanel {
let id = peer_id.map_or(usize::MAX, |id| id.as_u64() as usize);
ListItem::new(("screen", id))
.start_slot(render_tree_branch(is_last, cx))
.child(IconButton::new(0, Icon::Screen))
.start_slot(
h_stack()
.gap_1()
.child(render_tree_branch(is_last, cx))
.child(IconButton::new(0, Icon::Screen)),
)
.child(Label::new("Screen"))
.when_some(peer_id, |this, _| {
this.on_click(cx.listener(move |this, _, cx| {
@ -1372,9 +1376,13 @@ impl CollabPanel {
.on_click(cx.listener(move |this, _, cx| {
this.open_channel_notes(channel_id, cx);
}))
.start_slot(render_tree_branch(false, cx))
.child(IconButton::new(0, Icon::File))
.child(Label::new("notes"))
.start_slot(
h_stack()
.gap_1()
.child(render_tree_branch(false, cx))
.child(IconButton::new(0, Icon::File)),
)
.child(div().h_7().w_full().child(Label::new("notes")))
.tooltip(move |cx| Tooltip::text("Open Channel Notes", cx))
}
@ -1387,8 +1395,12 @@ impl CollabPanel {
.on_click(cx.listener(move |this, _, cx| {
this.join_channel_chat(channel_id, cx);
}))
.start_slot(render_tree_branch(true, cx))
.child(IconButton::new(0, Icon::MessageBubbles))
.start_slot(
h_stack()
.gap_1()
.child(render_tree_branch(false, cx))
.child(IconButton::new(0, Icon::MessageBubbles)),
)
.child(Label::new("chat"))
.tooltip(move |cx| Tooltip::text("Open Chat", cx))
}
@ -2149,11 +2161,6 @@ impl CollabPanel {
fn render_signed_in(&mut self, cx: &mut ViewContext<Self>) -> Div {
v_stack()
.size_full()
.child(
div()
.p_2()
.child(div().rounded(px(2.0)).child(self.filter_editor.clone())),
)
.child(
v_stack()
.size_full()
@ -2223,6 +2230,14 @@ impl CollabPanel {
}
})),
)
.child(
div().p_2().child(
div()
.border_primary(cx)
.border_t()
.child(self.filter_editor.clone()),
),
)
}
fn render_header(
@ -2274,22 +2289,32 @@ impl CollabPanel {
let button = match section {
Section::ActiveCall => channel_link.map(|channel_link| {
let channel_link_copy = channel_link.clone();
IconButton::new("channel-link", Icon::Copy)
.on_click(move |_, cx| {
let item = ClipboardItem::new(channel_link_copy.clone());
cx.write_to_clipboard(item)
})
.tooltip(|cx| Tooltip::text("Copy channel link", cx))
div()
.invisible()
.group_hover("section-header", |this| this.visible())
.child(
IconButton::new("channel-link", Icon::Copy)
.icon_size(IconSize::Small)
.size(ButtonSize::None)
.on_click(move |_, cx| {
let item = ClipboardItem::new(channel_link_copy.clone());
cx.write_to_clipboard(item)
})
.tooltip(|cx| Tooltip::text("Copy channel link", cx)),
)
.into_any_element()
}),
Section::Contacts => Some(
IconButton::new("add-contact", Icon::Plus)
.on_click(cx.listener(|this, _, cx| this.toggle_contact_finder(cx)))
.tooltip(|cx| Tooltip::text("Search for new contact", cx)),
.tooltip(|cx| Tooltip::text("Search for new contact", cx))
.into_any_element(),
),
Section::Channels => Some(
IconButton::new("add-channel", Icon::Plus)
.on_click(cx.listener(|this, _, cx| this.new_root_channel(cx)))
.tooltip(|cx| Tooltip::text("Create a channel", cx)),
.tooltip(|cx| Tooltip::text("Create a channel", cx))
.into_any_element(),
),
_ => None,
};
@ -2304,25 +2329,18 @@ impl CollabPanel {
h_stack()
.w_full()
.map(|el| {
if can_collapse {
el.child(
ListItem::new(text.clone())
.child(div().w_full().child(Label::new(text)))
.selected(is_selected)
.toggle(Some(!is_collapsed))
.on_click(cx.listener(move |this, _, cx| {
this.toggle_section_expanded(section, cx)
})),
)
} else {
el.child(
ListHeader::new(text)
.when_some(button, |el, button| el.end_slot(button))
.selected(is_selected),
)
}
})
.group("section-header")
.child(
ListHeader::new(text)
.toggle(if can_collapse {
Some(!is_collapsed)
} else {
None
})
.inset(true)
.end_slot::<AnyElement>(button)
.selected(is_selected),
)
.when(section == Section::Channels, |el| {
el.drag_over::<DraggedChannelView>(|style| {
style.bg(cx.theme().colors().ghost_element_hover)
@ -2460,7 +2478,7 @@ impl CollabPanel {
.child(Label::new(github_login.clone()))
.child(h_stack().children(controls)),
)
.start_slot::<Avatar>(user.avatar_uri.clone().map(|avatar| Avatar::new(avatar)))
.start_slot(Avatar::new(user.avatar_uri.clone()))
}
fn render_contact_placeholder(
@ -2541,6 +2559,8 @@ impl CollabPanel {
div()
.id(channel_id as usize)
.group("")
.flex()
.w_full()
.on_drag({
let channel = channel.clone();
move |cx| {
@ -2566,71 +2586,10 @@ impl CollabPanel {
)
.child(
ListItem::new(channel_id as usize)
.indent_level(depth)
// Offset the indent depth by one to give us room to show the disclosure.
.indent_level(depth + 1)
.indent_step_size(cx.rem_size() * 14.0 / 16.0) // @todo()! @nate this is to step over the disclosure toggle
.start_slot(
IconElement::new(if is_public { Icon::Public } else { Icon::Hash })
.size(IconSize::Small)
.color(Color::Muted),
)
.selected(is_selected || is_active)
.child(
h_stack()
.w_full()
.justify_between()
.child(
h_stack()
.id(channel_id as usize)
.child(Label::new(channel.name.clone()))
.children(face_pile.map(|face_pile| face_pile.render(cx))),
)
.child(
h_stack()
.child(
div()
.id("channel_chat")
.when(!has_messages_notification, |el| el.invisible())
.group_hover("", |style| style.visible())
.child(
IconButton::new(
"channel_chat",
Icon::MessageBubbles,
)
.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)
}),
),
)
.child(
div()
.id("channel_notes")
.when(!has_notes_notification, |el| el.invisible())
.group_hover("", |style| style.visible())
.child(
IconButton::new("channel_notes", Icon::File)
.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)
}),
),
),
),
)
.toggle(disclosed)
.on_toggle(
cx.listener(move |this, _, cx| {
@ -2650,7 +2609,57 @@ impl CollabPanel {
move |this, event: &MouseDownEvent, cx| {
this.deploy_channel_context_menu(event.position, channel_id, ix, cx)
},
)),
))
.start_slot(
IconElement::new(if is_public { Icon::Public } else { Icon::Hash })
.size(IconSize::Small)
.color(Color::Muted),
)
.child(
h_stack()
.id(channel_id as usize)
.child(Label::new(channel.name.clone()))
.children(face_pile.map(|face_pile| face_pile.render(cx))),
)
.end_slot(
h_stack()
.child(
div()
.id("channel_chat")
.when(!has_messages_notification, |el| el.invisible())
.group_hover("", |style| style.visible())
.child(
IconButton::new("channel_chat", Icon::MessageBubbles)
.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)),
),
)
.child(
div()
.id("channel_notes")
.when(!has_notes_notification, |el| el.invisible())
.group_hover("", |style| style.visible())
.child(
IconButton::new("channel_notes", Icon::File)
.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)),
),
),
),
)
.tooltip(|cx| Tooltip::text("Join channel", cx))

View file

@ -1,6 +1,7 @@
use crate::{prelude::*, Color, Icon, IconButton, IconSize};
use gpui::ClickEvent;
use crate::{prelude::*, Color, Icon, IconButton, IconSize};
#[derive(IntoElement)]
pub struct Disclosure {
is_open: bool,

View file

@ -1,9 +1,10 @@
use crate::{prelude::*, Disclosure};
use gpui::{
px, AnyElement, AnyView, ClickEvent, Div, MouseButton, MouseDownEvent, Pixels, Stateful,
};
use smallvec::SmallVec;
use crate::{prelude::*, Disclosure};
#[derive(IntoElement)]
pub struct ListItem {
id: ElementId,
@ -192,10 +193,15 @@ impl RenderOnce for ListItem {
this.ml(self.indent_level as f32 * self.indent_step_size)
}
})
.children(
self.toggle
.map(|is_open| Disclosure::new(is_open).on_toggle(self.on_toggle)),
)
.children(self.toggle.map(|is_open| {
div()
.flex()
.absolute()
.left(rems(-1.))
.invisible()
.group_hover("", |style| style.visible())
.child(Disclosure::new(is_open).on_toggle(self.on_toggle))
}))
.child(
h_stack()
.flex_1()

15
script/storybook Executable file
View file

@ -0,0 +1,15 @@
#!/bin/bash
# This script takes a single text input and replaces 'list_item' with the input in a cargo run command
# Check if an argument is provided
if [ "$#" -ne 1 ]; then
echo "Usage: $0 <component_name>"
exit 1
fi
# Assign the argument to a variable
COMPONENT_NAME="$1"
# Run the cargo command with the provided component name
cargo run -p storybook2 -- components/"$COMPONENT_NAME"