update sidebar

This commit is contained in:
2026-09-20 09:02:57 +07:00
parent 8401628412
commit 9c735febc1
6 changed files with 104 additions and 73 deletions
-6
View File
@@ -116,26 +116,20 @@ pub trait ButtonVariants: Sized {
#[allow(clippy::type_complexity)]
pub struct Button {
base: BaseButton,
icon: Option<Icon>,
label: Option<SharedString>,
tooltip: Option<SharedString>,
children: Vec<AnyElement>,
variant: ButtonVariant,
size: Size,
disabled: bool,
loading: bool,
rounded: bool,
compact: bool,
caret: bool,
indicator: bool,
on_click: Option<Rc<dyn Fn(&ClickEvent, &mut Window, &mut App)>>,
on_hover: Option<Rc<dyn Fn(&bool, &mut Window, &mut App)>>,
tab_index: isize,
tab_stop: bool,
+34 -28
View File
@@ -255,35 +255,40 @@ fn rows_for(tab: SidebarTab, cx: &App) -> Vec<SidebarRow> {
}];
}
let mut rows = vec![SidebarRow::Section {
label: "Communities".into(),
count: community_count,
}];
let mut rows = Vec::new();
rows.extend(
communities
.into_iter()
.map(|community| SidebarRow::Community { community }),
);
rows.push(SidebarRow::Action {
label: "Show all communities".into(),
tab: SidebarTab::Communities,
});
if !communities.is_empty() {
rows.push(SidebarRow::Section {
label: "Communities".into(),
count: community_count,
});
rows.extend(
communities
.into_iter()
.map(|community| SidebarRow::Community { community }),
);
rows.push(SidebarRow::Action {
label: "Show all communities".into(),
tab: SidebarTab::Communities,
});
}
rows.push(SidebarRow::Section {
label: "Chats".into(),
count: rooms.len(),
});
rows.extend(
rooms
.into_iter()
.take(5)
.map(|room| SidebarRow::Room { room }),
);
rows.push(SidebarRow::Action {
label: "Show all chats".into(),
tab: SidebarTab::Chats,
});
if !rooms.is_empty() {
rows.push(SidebarRow::Section {
label: "Chats".into(),
count: rooms.len(),
});
rows.extend(
rooms
.into_iter()
.take(5)
.map(|room| SidebarRow::Room { room }),
);
rows.push(SidebarRow::Action {
label: "Show all chats".into(),
tab: SidebarTab::Chats,
});
}
rows
}
@@ -400,6 +405,7 @@ fn render_rows(range: Range<usize>, rows: &[SidebarRow], cx: &Context<Sidebar>)
TreeRowKind::Action,
label.clone(),
)
.icon(IconName::ArrowRight)
.on_click(cx.listener(move |this, _event, _window, cx| {
this.select_tab(tab, cx);
}))
@@ -590,7 +596,7 @@ impl Render for Sidebar {
this.child(
div()
.absolute()
.bottom_12()
.bottom_16()
.left_0()
.h_9()
.w_full()
+32 -24
View File
@@ -1,7 +1,7 @@
use std::rc::Rc;
use gpui::prelude::FluentBuilder;
use gpui::{App, IntoElement, ParentElement, RenderOnce, Styled, Window, div};
use gpui::{App, InteractiveElement, IntoElement, ParentElement, RenderOnce, Styled, Window, div};
use theme::ActiveTheme;
use ui::button::{Button, ButtonVariants};
use ui::{IconName, Selectable, h_flex};
@@ -85,29 +85,37 @@ impl RenderOnce for TabBar {
fn render(self, _window: &mut Window, cx: &mut App) -> impl IntoElement {
let Self { active, on_select } = self;
div().absolute().bottom_2().left_0().w_full().px_2().child(
h_flex()
.w_full()
.p_1()
.gap_1()
.rounded(cx.theme().radius_lg)
.bg(cx.theme().elevated_surface_background)
.when(cx.theme().shadow, |this| this.shadow_md())
.children(SidebarTab::ALL.into_iter().map(|tab| {
let on_select = on_select.clone();
div()
.id("sidebar-tabs")
.absolute()
.bottom_3()
.left_0()
.w_full()
.px_4()
.child(
h_flex()
.w_full()
.p_1()
.gap_1()
.rounded_full()
.bg(cx.theme().background)
.when(cx.theme().shadow, |this| this.shadow_md())
.children(SidebarTab::ALL.into_iter().map(|tab| {
let on_select = on_select.clone();
Button::new(format!("tab-{}", tab.list_id()))
.icon(tab.icon())
.ghost()
.flex_1()
.selected(tab == active)
.tooltip(tab.label())
.on_click(move |_event, window, cx| {
if let Some(on_select) = on_select.as_ref() {
on_select(tab, window, cx);
}
})
})),
)
Button::new(format!("tab-{}", tab.list_id()))
.icon(tab.icon())
.ghost()
.flex_1()
.rounded()
.selected(tab == active)
.tooltip(tab.label())
.on_click(move |_event, window, cx| {
if let Some(on_select) = on_select.as_ref() {
on_select(tab, window, cx);
}
})
})),
)
}
}
+25 -7
View File
@@ -5,7 +5,7 @@ use community::Community;
use gpui::prelude::FluentBuilder;
use gpui::{
App, ClickEvent, ElementId, Entity, ImageSource, InteractiveElement, IntoElement,
ParentElement, RenderOnce, SharedString, StatefulInteractiveElement, Styled, Window, div,
ParentElement, RenderOnce, SharedString, StatefulInteractiveElement, Styled, Window, div, px,
};
use settings::AppSettings;
use theme::ActiveTheme;
@@ -50,6 +50,7 @@ pub struct TreeRow {
label: SharedString,
avatar: Option<SharedString>,
picture: Option<ImageSource>,
icon: Option<IconName>,
count: Option<usize>,
created_at: Option<SharedString>,
selected: bool,
@@ -69,6 +70,7 @@ impl TreeRow {
label: label.into(),
avatar: None,
picture: None,
icon: None,
count: None,
created_at: None,
selected: false,
@@ -88,6 +90,12 @@ impl TreeRow {
self
}
/// Shows `icon` in the avatar slot when the row has no avatar or picture.
pub fn icon(mut self, icon: IconName) -> Self {
self.icon = Some(icon);
self
}
pub fn count(mut self, count: usize) -> Self {
self.count = Some(count);
self
@@ -150,6 +158,18 @@ impl RenderOnce for TreeRow {
}
};
let avatar = avatar.or_else(|| {
self.icon.map(|icon| {
h_flex()
.flex_shrink_0()
.w(px(20.))
.justify_center()
.text_color(cx.theme().icon_muted)
.child(Icon::new(icon).small())
.into_any_element()
})
});
h_flex()
.id(self.id)
.h_8()
@@ -159,14 +179,12 @@ impl RenderOnce for TreeRow {
.rounded(cx.theme().radius)
.when(is_section, |this| {
this.text_xs()
.text_color(cx.theme().text_muted)
.text_color(cx.theme().text_placeholder)
.font_semibold()
})
.when(is_room || is_community, |this| this.text_sm())
.when(is_action, |this| {
this.text_sm()
.font_medium()
.text_color(cx.theme().text_accent)
this.text_sm().text_color(cx.theme().text_muted)
})
.when(is_hint, |this| {
this.text_xs()
@@ -197,11 +215,11 @@ impl RenderOnce for TreeRow {
this.child(div().flex_shrink_0().font_normal().child(count.to_string()))
})
.when_some(self.created_at, |this, created_at| {
this.child(
this.child(div().flex_1()).child(
div()
.flex_shrink_0()
.text_xs()
.text_color(cx.theme().text_placeholder)
.text_xs()
.child(created_at),
)
}),