sidebar: Fix sidebar example and add right side example. (#626)

This commit is contained in:
Jason Lee 2025-02-14 15:06:37 +08:00 committed by GitHub
parent cca6277ea5
commit bf300a2880
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 56 additions and 10 deletions

View file

@ -19,7 +19,7 @@ impl Example {
impl Render for Example { impl Render for Example {
fn render(&mut self, _window: &mut Window, _cx: &mut Context<Self>) -> impl IntoElement { fn render(&mut self, _window: &mut Window, _cx: &mut Context<Self>) -> impl IntoElement {
div().p_4().size_full().child(self.root.clone()) div().mt(-px(1.)).size_full().child(self.root.clone())
} }
} }

View file

@ -1,6 +1,6 @@
use gpui::{ use gpui::{
div, impl_internal_actions, prelude::FluentBuilder, relative, App, AppContext, ClickEvent, div, impl_internal_actions, prelude::FluentBuilder, relative, App, AppContext, ClickEvent,
Context, Entity, Focusable, ParentElement, Render, SharedString, Styled, Window, Context, Entity, Focusable, IntoElement, ParentElement, Render, SharedString, Styled, Window,
}; };
use gpui_component::{ use gpui_component::{
@ -12,7 +12,8 @@ use gpui_component::{
sidebar::{ sidebar::{
Sidebar, SidebarFooter, SidebarGroup, SidebarHeader, SidebarMenu, SidebarToggleButton, Sidebar, SidebarFooter, SidebarGroup, SidebarHeader, SidebarMenu, SidebarToggleButton,
}, },
v_flex, white, ActiveTheme, Collapsible, Icon, IconName, switch::Switch,
v_flex, white, ActiveTheme, Collapsible, Icon, IconName, Side,
}; };
use serde::Deserialize; use serde::Deserialize;
@ -25,6 +26,7 @@ pub struct SidebarStory {
active_item: Item, active_item: Item,
active_subitem: Option<SubItem>, active_subitem: Option<SubItem>,
is_collapsed: bool, is_collapsed: bool,
side: Side,
focus_handle: gpui::FocusHandle, focus_handle: gpui::FocusHandle,
} }
@ -38,9 +40,24 @@ impl SidebarStory {
active_item: Item::Playground, active_item: Item::Playground,
active_subitem: None, active_subitem: None,
is_collapsed: false, is_collapsed: false,
side: Side::Left,
focus_handle: cx.focus_handle(), focus_handle: cx.focus_handle(),
} }
} }
fn render_content(&mut self, _: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
v_flex().child(
h_flex().gap_2().child(
Switch::new("side")
.label("Placement Right")
.checked(self.side.is_right())
.on_click(cx.listener(|this, checked: &bool, _, cx| {
this.side = if *checked { Side::Right } else { Side::Left };
cx.notify();
})),
),
)
}
} }
#[derive(Clone, Copy, PartialEq, Eq)] #[derive(Clone, Copy, PartialEq, Eq)]
@ -174,6 +191,7 @@ impl super::Story for SidebarStory {
Self::view(window, cx) Self::view(window, cx)
} }
} }
impl Focusable for SidebarStory { impl Focusable for SidebarStory {
fn focus_handle(&self, _: &gpui::App) -> gpui::FocusHandle { fn focus_handle(&self, _: &gpui::App) -> gpui::FocusHandle {
self.focus_handle.clone() self.focus_handle.clone()
@ -182,7 +200,7 @@ impl Focusable for SidebarStory {
impl Render for SidebarStory { impl Render for SidebarStory {
fn render( fn render(
&mut self, &mut self,
_: &mut gpui::Window, window: &mut gpui::Window,
cx: &mut gpui::Context<Self>, cx: &mut gpui::Context<Self>,
) -> impl gpui::IntoElement { ) -> impl gpui::IntoElement {
let groups: [Vec<Item>; 2] = [ let groups: [Vec<Item>; 2] = [
@ -199,13 +217,20 @@ impl Render for SidebarStory {
], ],
]; ];
let sidebar = if self.side.is_left() {
Sidebar::left(&cx.entity())
} else {
Sidebar::right(&cx.entity())
};
h_flex() h_flex()
.rounded(cx.theme().radius) .rounded(cx.theme().radius)
.border_1() .border_1()
.border_color(cx.theme().border) .border_color(cx.theme().border)
.h_full() .h_full()
.when(self.side.is_right(), |this| this.flex_row_reverse())
.child( .child(
Sidebar::left(&cx.entity()) sidebar
.collapsed(self.is_collapsed) .collapsed(self.is_collapsed)
.header( .header(
SidebarHeader::new() SidebarHeader::new()
@ -221,9 +246,14 @@ impl Render for SidebarStory {
.text_color(white()) .text_color(white())
.size_8() .size_8()
.flex_shrink_0() .flex_shrink_0()
.child(Icon::new(IconName::GalleryVerticalEnd).size_4()) .when(!self.is_collapsed, |this| {
this.child(Icon::new(IconName::GalleryVerticalEnd).size_4())
})
.when(self.is_collapsed, |this| { .when(self.is_collapsed, |this| {
this.size_4().bg(cx.theme().transparent) this.size_4()
.bg(cx.theme().transparent)
.text_color(cx.theme().foreground)
.child(Icon::new(IconName::GalleryVerticalEnd).size_5())
}), }),
) )
.when(!self.is_collapsed, |this| { .when(!self.is_collapsed, |this| {
@ -326,8 +356,12 @@ impl Render for SidebarStory {
h_flex() h_flex()
.items_center() .items_center()
.gap_3() .gap_3()
.when(self.side.is_right(), |this| {
this.flex_row_reverse().justify_between()
})
.child( .child(
SidebarToggleButton::left() SidebarToggleButton::left()
.side(self.side)
.collapsed(self.is_collapsed) .collapsed(self.is_collapsed)
.on_click(cx.listener(|this, _, _, cx| { .on_click(cx.listener(|this, _, _, cx| {
this.is_collapsed = !this.is_collapsed; this.is_collapsed = !this.is_collapsed;
@ -355,7 +389,7 @@ impl Render for SidebarStory {
}), }),
), ),
) )
.child("This content"), .child(self.render_content(window, cx)),
) )
} }
} }

View file

@ -132,6 +132,11 @@ impl SidebarToggleButton {
Self::new(Side::Right) Self::new(Side::Right)
} }
pub fn side(mut self, side: Side) -> Self {
self.side = side;
self
}
pub fn collapsed(mut self, is_collapsed: bool) -> Self { pub fn collapsed(mut self, is_collapsed: bool) -> Self {
self.is_collapsed = is_collapsed; self.is_collapsed = is_collapsed;
self self
@ -191,7 +196,7 @@ impl<E: Collapsible + IntoElement> RenderOnce for Sidebar<E> {
.border_color(cx.theme().sidebar_border) .border_color(cx.theme().sidebar_border)
.map(|this| match self.side { .map(|this| match self.side {
Side::Left => this.border_r_1(), Side::Left => this.border_r_1(),
Side::Right => this.text_2xl(), Side::Right => this.border_l_1(),
}) })
.when_some(self.header.take(), |this, header| { .when_some(self.header.take(), |this, header| {
this.child(h_flex().id("header").p_2().gap_2().child(header)) this.child(h_flex().id("header").p_2().gap_2().child(header))

View file

@ -443,10 +443,17 @@ pub enum Side {
} }
impl Side { impl Side {
/// Returns true if the side is left.
#[inline] #[inline]
pub(crate) fn is_left(&self) -> bool { pub fn is_left(&self) -> bool {
matches!(self, Self::Left) matches!(self, Self::Left)
} }
/// Returns true if the side is right.
#[inline]
pub fn is_right(&self) -> bool {
matches!(self, Self::Right)
}
} }
/// A trait for defining element that can be collapsed. /// A trait for defining element that can be collapsed.