Add `RecentProjects` component

Marshall Bowers created

Change summary

crates/storybook2/src/stories/components.rs                 |  1 
crates/storybook2/src/stories/components/recent_projects.rs | 26 +++++
crates/storybook2/src/story_selector.rs                     |  4 
crates/ui2/src/components.rs                                |  2 
crates/ui2/src/components/recent_projects.rs                | 36 ++++++
5 files changed, 69 insertions(+)

Detailed changes

crates/storybook2/src/stories/components/recent_projects.rs 🔗

@@ -0,0 +1,26 @@
+use std::marker::PhantomData;
+
+use ui::prelude::*;
+use ui::RecentProjects;
+
+use crate::story::Story;
+
+#[derive(Element)]
+pub struct RecentProjectsStory<S: 'static + Send + Sync + Clone> {
+    state_type: PhantomData<S>,
+}
+
+impl<S: 'static + Send + Sync + Clone> RecentProjectsStory<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::<_, RecentProjects<S>>(cx))
+            .child(Story::label(cx, "Default"))
+            .child(RecentProjects::new())
+    }
+}

crates/storybook2/src/story_selector.rs 🔗

@@ -50,6 +50,7 @@ pub enum ComponentStory {
     Palette,
     Panel,
     ProjectPanel,
+    RecentProjects,
     Tab,
     TabBar,
     Terminal,
@@ -86,6 +87,9 @@ impl ComponentStory {
             Self::Palette => components::palette::PaletteStory::new().into_any(),
             Self::Panel => components::panel::PanelStory::new().into_any(),
             Self::ProjectPanel => components::project_panel::ProjectPanelStory::new().into_any(),
+            Self::RecentProjects => {
+                components::recent_projects::RecentProjectsStory::new().into_any()
+            }
             Self::Tab => components::tab::TabStory::new().into_any(),
             Self::TabBar => components::tab_bar::TabBarStory::new().into_any(),
             Self::Terminal => components::terminal::TerminalStory::new().into_any(),

crates/ui2/src/components.rs 🔗

@@ -17,6 +17,7 @@ mod panel;
 mod panes;
 mod player_stack;
 mod project_panel;
+mod recent_projects;
 mod status_bar;
 mod tab;
 mod tab_bar;
@@ -47,6 +48,7 @@ pub use panel::*;
 pub use panes::*;
 pub use player_stack::*;
 pub use project_panel::*;
+pub use recent_projects::*;
 pub use status_bar::*;
 pub use tab::*;
 pub use tab_bar::*;

crates/ui2/src/components/recent_projects.rs 🔗

@@ -0,0 +1,36 @@
+use std::marker::PhantomData;
+
+use crate::prelude::*;
+use crate::{OrderMethod, Palette, PaletteItem};
+
+#[derive(Element)]
+pub struct RecentProjects<S: 'static + Send + Sync + Clone> {
+    state_type: PhantomData<S>,
+    scroll_state: ScrollState,
+}
+
+impl<S: 'static + Send + Sync + Clone> RecentProjects<S> {
+    pub fn new() -> Self {
+        Self {
+            state_type: PhantomData,
+            scroll_state: ScrollState::default(),
+        }
+    }
+
+    fn render(&mut self, cx: &mut ViewContext<S>) -> impl Element<State = S> {
+        div().child(
+            Palette::new(self.scroll_state.clone())
+                .items(vec![
+                    PaletteItem::new("zed").sublabel("~/projects/zed"),
+                    PaletteItem::new("saga").sublabel("~/projects/saga"),
+                    PaletteItem::new("journal").sublabel("~/journal"),
+                    PaletteItem::new("dotfiles").sublabel("~/dotfiles"),
+                    PaletteItem::new("zed.dev").sublabel("~/projects/zed.dev"),
+                    PaletteItem::new("laminar").sublabel("~/projects/laminar"),
+                ])
+                .placeholder("Recent Projects...")
+                .empty_string("No matches")
+                .default_order(OrderMethod::Ascending),
+        )
+    }
+}