Add CollabPanel component

This commit is contained in:
Marshall Bowers 2023-10-09 11:04:53 -04:00
parent 8814ea8241
commit 4eeed14d34
6 changed files with 271 additions and 3 deletions

View file

@ -2,6 +2,7 @@ pub mod assistant_panel;
pub mod breadcrumb;
pub mod buffer;
pub mod chat_panel;
pub mod collab_panel;
pub mod facepile;
pub mod panel;
pub mod project_panel;

View file

@ -0,0 +1,26 @@
use std::marker::PhantomData;
use ui::prelude::*;
use ui::CollabPanel;
use crate::story::Story;
#[derive(Element)]
pub struct CollabPanelStory<S: 'static + Send + Sync + Clone> {
state_type: PhantomData<S>,
}
impl<S: 'static + Send + Sync + Clone> CollabPanelStory<S> {
pub fn new() -> Self {
Self {
state_type: PhantomData,
}
}
fn render(&mut self, cx: &mut ViewContext<S>) -> impl Element<State = S> {
Story::container(cx)
.child(Story::title_for::<_, CollabPanel<S>>(cx))
.child(Story::label(cx, "Default"))
.child(CollabPanel::new(ScrollState::default()))
}
}

View file

@ -40,6 +40,7 @@ pub enum ComponentStory {
Breadcrumb,
Buffer,
ChatPanel,
CollabPanel,
Facepile,
Panel,
ProjectPanel,
@ -63,6 +64,7 @@ impl ComponentStory {
Self::Buffer => components::buffer::BufferStory::new().into_any(),
Self::Breadcrumb => components::breadcrumb::BreadcrumbStory::new().into_any(),
Self::ChatPanel => components::chat_panel::ChatPanelStory::new().into_any(),
Self::CollabPanel => components::collab_panel::CollabPanelStory::new().into_any(),
Self::Facepile => components::facepile::FacepileStory::new().into_any(),
Self::Panel => components::panel::PanelStory::new().into_any(),
Self::ProjectPanel => components::project_panel::ProjectPanelStory::new().into_any(),

View file

@ -2,6 +2,7 @@ mod assistant_panel;
mod breadcrumb;
mod buffer;
mod chat_panel;
mod collab_panel;
mod editor_pane;
mod facepile;
mod icon_button;
@ -23,6 +24,7 @@ pub use assistant_panel::*;
pub use breadcrumb::*;
pub use buffer::*;
pub use chat_panel::*;
pub use collab_panel::*;
pub use editor_pane::*;
pub use facepile::*;
pub use icon_button::*;

View file

@ -0,0 +1,160 @@
use std::marker::PhantomData;
use gpui3::{img, svg, ArcCow};
use crate::prelude::*;
use crate::theme::{theme, Theme};
use crate::{
static_collab_panel_channels, static_collab_panel_current_call, v_stack, Icon, List,
ListHeader, ToggleState,
};
#[derive(Element)]
pub struct CollabPanel<S: 'static + Send + Sync + Clone> {
view_type: PhantomData<S>,
scroll_state: ScrollState,
}
impl<S: 'static + Send + Sync + Clone> CollabPanel<S> {
pub fn new(scroll_state: ScrollState) -> Self {
Self {
view_type: PhantomData,
scroll_state,
}
}
fn render(&mut self, cx: &mut ViewContext<S>) -> impl Element<State = S> {
let theme = theme(cx);
v_stack()
.w_64()
.h_full()
.fill(theme.middle.base.default.background)
.child(
v_stack()
.w_full()
.overflow_y_scroll(self.scroll_state.clone())
.child(
div()
.fill(theme.lowest.base.default.background)
.pb_1()
.border_color(theme.lowest.base.default.border)
.border_b()
.child(
List::new(static_collab_panel_current_call())
.header(
ListHeader::new("CRDB")
.left_icon(Icon::Hash.into())
.set_toggle(ToggleState::Toggled),
)
.set_toggle(ToggleState::Toggled),
),
)
.child(
v_stack().py_1().child(
List::new(static_collab_panel_channels())
.header(
ListHeader::new("CHANNELS").set_toggle(ToggleState::Toggled),
)
.empty_message("No channels yet. Add a channel to get started.")
.set_toggle(ToggleState::Toggled),
),
)
.child(
v_stack().py_1().child(
List::new(static_collab_panel_current_call())
.header(
ListHeader::new("CONTACTS ONLINE")
.set_toggle(ToggleState::Toggled),
)
.set_toggle(ToggleState::Toggled),
),
)
.child(
v_stack().py_1().child(
List::new(static_collab_panel_current_call())
.header(
ListHeader::new("CONTACTS OFFLINE")
.set_toggle(ToggleState::NotToggled),
)
.set_toggle(ToggleState::NotToggled),
),
),
)
.child(
div()
.h_7()
.px_2()
.border_t()
.border_color(theme.middle.variant.default.border)
.flex()
.items_center()
.child(
div()
.text_sm()
.text_color(theme.middle.variant.default.foreground)
.child("Find..."),
),
)
}
fn list_section_header(
&self,
label: impl Into<ArcCow<'static, str>>,
expanded: bool,
theme: &Theme,
) -> impl Element<State = S> {
div()
.h_7()
.px_2()
.flex()
.justify_between()
.items_center()
.child(div().flex().gap_1().text_sm().child(label.into()))
.child(
div().flex().h_full().gap_1().items_center().child(
svg()
.path(if expanded {
"icons/caret_down.svg"
} else {
"icons/caret_up.svg"
})
.w_3p5()
.h_3p5()
.fill(theme.middle.variant.default.foreground),
),
)
}
fn list_item(
&self,
avatar_uri: impl Into<ArcCow<'static, str>>,
label: impl Into<ArcCow<'static, str>>,
theme: &Theme,
) -> impl Element<State = S> {
div()
.h_7()
.px_2()
.flex()
.items_center()
// .hover()
// .fill(theme.lowest.variant.hovered.background)
// .active()
// .fill(theme.lowest.variant.pressed.background)
.child(
div()
.flex()
.items_center()
.gap_1()
.text_sm()
.child(
img()
.uri(avatar_uri)
.size_3p5()
.rounded_full()
.fill(theme.middle.positive.default.foreground),
)
.child(label.into()),
)
}
}

View file

@ -5,9 +5,9 @@ use rand::Rng;
use crate::{
Buffer, BufferRow, BufferRows, Editor, FileSystemStatus, GitStatus, HighlightColor,
HighlightedLine, HighlightedText, Icon, Label, LabelColor, ListEntry, ListItem, Livestream,
MicStatus, Player, PlayerCallStatus, PlayerWithCallStatus, ScreenShareStatus, Symbol, Tab,
Theme, ToggleState, VideoStatus,
HighlightedLine, HighlightedText, Icon, Label, LabelColor, ListEntry, ListEntrySize, ListItem,
Livestream, MicStatus, Player, PlayerCallStatus, PlayerWithCallStatus, ScreenShareStatus,
Symbol, Tab, Theme, ToggleState, VideoStatus,
};
pub fn static_tabs_example<S: 'static + Send + Sync + Clone>() -> Vec<Tab<S>> {
@ -464,6 +464,83 @@ pub fn static_project_panel_single_items<S: 'static + Send + Sync + Clone>() ->
.collect()
}
pub fn static_collab_panel_current_call<S: 'static + Send + Sync + Clone>() -> Vec<ListItem<S>> {
vec![
ListEntry::new(Label::new("as-cii")).left_avatar("http://github.com/as-cii.png?s=50"),
ListEntry::new(Label::new("nathansobo"))
.left_avatar("http://github.com/nathansobo.png?s=50"),
ListEntry::new(Label::new("maxbrunsfeld"))
.left_avatar("http://github.com/maxbrunsfeld.png?s=50"),
]
.into_iter()
.map(From::from)
.collect()
}
pub fn static_collab_panel_channels<S: 'static + Send + Sync + Clone>() -> Vec<ListItem<S>> {
vec![
ListEntry::new(Label::new("zed"))
.left_icon(Icon::Hash.into())
.size(ListEntrySize::Medium)
.indent_level(0),
ListEntry::new(Label::new("community"))
.left_icon(Icon::Hash.into())
.size(ListEntrySize::Medium)
.indent_level(1),
ListEntry::new(Label::new("dashboards"))
.left_icon(Icon::Hash.into())
.size(ListEntrySize::Medium)
.indent_level(2),
ListEntry::new(Label::new("feedback"))
.left_icon(Icon::Hash.into())
.size(ListEntrySize::Medium)
.indent_level(2),
ListEntry::new(Label::new("teams-in-channels-alpha"))
.left_icon(Icon::Hash.into())
.size(ListEntrySize::Medium)
.indent_level(2),
ListEntry::new(Label::new("current-projects"))
.left_icon(Icon::Hash.into())
.size(ListEntrySize::Medium)
.indent_level(1),
ListEntry::new(Label::new("codegen"))
.left_icon(Icon::Hash.into())
.size(ListEntrySize::Medium)
.indent_level(2),
ListEntry::new(Label::new("gpui2"))
.left_icon(Icon::Hash.into())
.size(ListEntrySize::Medium)
.indent_level(2),
ListEntry::new(Label::new("livestreaming"))
.left_icon(Icon::Hash.into())
.size(ListEntrySize::Medium)
.indent_level(2),
ListEntry::new(Label::new("open-source"))
.left_icon(Icon::Hash.into())
.size(ListEntrySize::Medium)
.indent_level(2),
ListEntry::new(Label::new("replace"))
.left_icon(Icon::Hash.into())
.size(ListEntrySize::Medium)
.indent_level(2),
ListEntry::new(Label::new("semantic-index"))
.left_icon(Icon::Hash.into())
.size(ListEntrySize::Medium)
.indent_level(2),
ListEntry::new(Label::new("vim"))
.left_icon(Icon::Hash.into())
.size(ListEntrySize::Medium)
.indent_level(2),
ListEntry::new(Label::new("web-tech"))
.left_icon(Icon::Hash.into())
.size(ListEntrySize::Medium)
.indent_level(2),
]
.into_iter()
.map(From::from)
.collect()
}
pub fn empty_editor_example<S: 'static + Send + Sync + Clone>() -> Editor<S> {
Editor {
tabs: static_tabs_example(),