From bf300a288063e9a5aec4f033eb6fb7a9bcade254 Mon Sep 17 00:00:00 2001 From: Jason Lee Date: Fri, 14 Feb 2025 15:06:37 +0800 Subject: [PATCH] sidebar: Fix sidebar example and add right side example. (#626) --- crates/story/examples/sidebar.rs | 2 +- crates/story/src/sidebar_story.rs | 48 ++++++++++++++++++++++++++----- crates/ui/src/sidebar/mod.rs | 7 ++++- crates/ui/src/styled.rs | 9 +++++- 4 files changed, 56 insertions(+), 10 deletions(-) diff --git a/crates/story/examples/sidebar.rs b/crates/story/examples/sidebar.rs index 244069ea..f373f315 100644 --- a/crates/story/examples/sidebar.rs +++ b/crates/story/examples/sidebar.rs @@ -19,7 +19,7 @@ impl Example { impl Render for Example { fn render(&mut self, _window: &mut Window, _cx: &mut Context) -> impl IntoElement { - div().p_4().size_full().child(self.root.clone()) + div().mt(-px(1.)).size_full().child(self.root.clone()) } } diff --git a/crates/story/src/sidebar_story.rs b/crates/story/src/sidebar_story.rs index 0d1ec7c4..bdb7ecad 100644 --- a/crates/story/src/sidebar_story.rs +++ b/crates/story/src/sidebar_story.rs @@ -1,6 +1,6 @@ use gpui::{ 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::{ @@ -12,7 +12,8 @@ use gpui_component::{ sidebar::{ 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; @@ -25,6 +26,7 @@ pub struct SidebarStory { active_item: Item, active_subitem: Option, is_collapsed: bool, + side: Side, focus_handle: gpui::FocusHandle, } @@ -38,9 +40,24 @@ impl SidebarStory { active_item: Item::Playground, active_subitem: None, is_collapsed: false, + side: Side::Left, focus_handle: cx.focus_handle(), } } + + fn render_content(&mut self, _: &mut Window, cx: &mut Context) -> 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)] @@ -174,6 +191,7 @@ impl super::Story for SidebarStory { Self::view(window, cx) } } + impl Focusable for SidebarStory { fn focus_handle(&self, _: &gpui::App) -> gpui::FocusHandle { self.focus_handle.clone() @@ -182,7 +200,7 @@ impl Focusable for SidebarStory { impl Render for SidebarStory { fn render( &mut self, - _: &mut gpui::Window, + window: &mut gpui::Window, cx: &mut gpui::Context, ) -> impl gpui::IntoElement { let groups: [Vec; 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() .rounded(cx.theme().radius) .border_1() .border_color(cx.theme().border) .h_full() + .when(self.side.is_right(), |this| this.flex_row_reverse()) .child( - Sidebar::left(&cx.entity()) + sidebar .collapsed(self.is_collapsed) .header( SidebarHeader::new() @@ -221,9 +246,14 @@ impl Render for SidebarStory { .text_color(white()) .size_8() .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| { - 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| { @@ -326,8 +356,12 @@ impl Render for SidebarStory { h_flex() .items_center() .gap_3() + .when(self.side.is_right(), |this| { + this.flex_row_reverse().justify_between() + }) .child( SidebarToggleButton::left() + .side(self.side) .collapsed(self.is_collapsed) .on_click(cx.listener(|this, _, _, cx| { this.is_collapsed = !this.is_collapsed; @@ -355,7 +389,7 @@ impl Render for SidebarStory { }), ), ) - .child("This content"), + .child(self.render_content(window, cx)), ) } } diff --git a/crates/ui/src/sidebar/mod.rs b/crates/ui/src/sidebar/mod.rs index 96168185..43d177a8 100644 --- a/crates/ui/src/sidebar/mod.rs +++ b/crates/ui/src/sidebar/mod.rs @@ -132,6 +132,11 @@ impl SidebarToggleButton { 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 { self.is_collapsed = is_collapsed; self @@ -191,7 +196,7 @@ impl RenderOnce for Sidebar { .border_color(cx.theme().sidebar_border) .map(|this| match self.side { Side::Left => this.border_r_1(), - Side::Right => this.text_2xl(), + Side::Right => this.border_l_1(), }) .when_some(self.header.take(), |this, header| { this.child(h_flex().id("header").p_2().gap_2().child(header)) diff --git a/crates/ui/src/styled.rs b/crates/ui/src/styled.rs index 23135a56..30706047 100644 --- a/crates/ui/src/styled.rs +++ b/crates/ui/src/styled.rs @@ -443,10 +443,17 @@ pub enum Side { } impl Side { + /// Returns true if the side is left. #[inline] - pub(crate) fn is_left(&self) -> bool { + pub fn is_left(&self) -> bool { 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.