use gpui::{prelude::*, *}; use gpui_component::{ h_flex, sidebar::{Sidebar, SidebarGroup, SidebarHeader, SidebarMenu, SidebarMenuItem}, v_flex, ActiveTheme as _, Icon, IconName, }; use story::*; pub struct Gallery { stories: Vec<(&'static str, Vec>)>, active_group_index: usize, active_index: usize, collapsed: bool, } impl Gallery { pub fn new(window: &mut Window, cx: &mut Context) -> Self { let stories = vec![ ( "Getting Started", vec![StoryContainer::panel::(window, cx)], ), ( "Components", vec![ StoryContainer::panel::(window, cx), StoryContainer::panel::(window, cx), StoryContainer::panel::(window, cx), StoryContainer::panel::(window, cx), StoryContainer::panel::(window, cx), StoryContainer::panel::(window, cx), StoryContainer::panel::(window, cx), StoryContainer::panel::(window, cx), StoryContainer::panel::(window, cx), StoryContainer::panel::(window, cx), StoryContainer::panel::(window, cx), StoryContainer::panel::(window, cx), StoryContainer::panel::(window, cx), StoryContainer::panel::(window, cx), StoryContainer::panel::(window, cx), StoryContainer::panel::(window, cx), StoryContainer::panel::(window, cx), StoryContainer::panel::(window, cx), StoryContainer::panel::(window, cx), StoryContainer::panel::(window, cx), StoryContainer::panel::(window, cx), StoryContainer::panel::(window, cx), StoryContainer::panel::(window, cx), StoryContainer::panel::(window, cx), StoryContainer::panel::(window, cx), StoryContainer::panel::(window, cx), StoryContainer::panel::(window, cx), StoryContainer::panel::(window, cx), StoryContainer::panel::(window, cx), StoryContainer::panel::(window, cx), StoryContainer::panel::(window, cx), StoryContainer::panel::(window, cx), ], ), ]; Self { stories, active_group_index: 0, active_index: 0, collapsed: false, } } fn view(window: &mut Window, cx: &mut App) -> Entity { cx.new(|cx| Self::new(window, cx)) } } impl Render for Gallery { fn render(&mut self, _: &mut Window, cx: &mut Context) -> impl IntoElement { let active_group = &self.stories[self.active_group_index]; let stories = &active_group.1; let active_story = stories[self.active_index].clone(); let story_name = active_story.read(cx).name.clone(); let description = active_story.read(cx).description.clone(); h_flex() .id("gallery-container") .size_full() .child( Sidebar::left() .collapsed(self.collapsed) .header( SidebarHeader::new() .w_full() .child( div() .flex() .items_center() .justify_center() .rounded(cx.theme().radius) .bg(cx.theme().primary) .text_color(cx.theme().primary_foreground) .size_8() .flex_shrink_0() .when(!self.collapsed, |this| { this.child(Icon::new(IconName::GalleryVerticalEnd)) }) .when(self.collapsed, |this| { this.size_4() .bg(cx.theme().transparent) .text_color(cx.theme().foreground) .child(Icon::new(IconName::GalleryVerticalEnd)) }) .rounded_lg(), ) .when(!self.collapsed, |this| { this.child( v_flex() .gap_0() .text_sm() .flex_1() .line_height(relative(1.25)) .overflow_hidden() .text_ellipsis() .child("GPUI Component") .child(div().child("Gallery").text_xs()), ) }), ) .children(self.stories.iter().enumerate().map( |(group_ix, (group_name, stories))| { SidebarGroup::new(*group_name).child(SidebarMenu::new().children( stories.iter().enumerate().map(|(ix, story)| { SidebarMenuItem::new(story.read(cx).name.clone()) .active( self.active_group_index == group_ix && self.active_index == ix, ) .on_click(cx.listener( move |this, _: &ClickEvent, _, cx| { this.active_group_index = group_ix; this.active_index = ix; cx.notify(); }, )) }), )) }, )), ) .child( v_flex() .flex_1() .h_full() .overflow_x_hidden() .child( h_flex() .id("header") .p_4() .border_b_1() .border_color(cx.theme().border) .justify_between() .items_start() .child( v_flex() .gap_1() .child(div().text_xl().child(story_name)) .child( div() .text_color(cx.theme().muted_foreground) .child(description), ), ), ) .child( div() .id("story") .flex_1() .overflow_y_scroll() .child(active_story), ), ) } } fn main() { let app = Application::new().with_assets(Assets); app.run(move |cx| { story::init(cx); cx.activate(true); story::create_new_window("Gallery of GPUI Component", Gallery::view, cx); }); }