diff --git a/Cargo.lock b/Cargo.lock index 05b29aabf4..9d6358edb4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -7390,6 +7390,7 @@ name = "storybook" version = "0.1.0" dependencies = [ "anyhow", + "clap 3.2.25", "gpui2", "log", "rust-embed", diff --git a/crates/storybook/Cargo.toml b/crates/storybook/Cargo.toml index c1096a87ba..882a1a1bdb 100644 --- a/crates/storybook/Cargo.toml +++ b/crates/storybook/Cargo.toml @@ -9,8 +9,9 @@ name = "storybook" path = "src/storybook.rs" [dependencies] -gpui2 = { path = "../gpui2" } anyhow.workspace = true +clap = { version = "3.1", features = ["derive"] } +gpui2 = { path = "../gpui2" } log.workspace = true rust-embed.workspace = true serde.workspace = true diff --git a/crates/storybook/src/stories.rs b/crates/storybook/src/stories.rs new file mode 100644 index 0000000000..57674c3c70 --- /dev/null +++ b/crates/storybook/src/stories.rs @@ -0,0 +1,2 @@ +pub mod components; +pub mod elements; diff --git a/crates/storybook/src/stories/components.rs b/crates/storybook/src/stories/components.rs new file mode 100644 index 0000000000..5e3d309419 --- /dev/null +++ b/crates/storybook/src/stories/components.rs @@ -0,0 +1 @@ +pub mod facepile; diff --git a/crates/storybook/src/stories/components/facepile.rs b/crates/storybook/src/stories/components/facepile.rs new file mode 100644 index 0000000000..6bde4539ed --- /dev/null +++ b/crates/storybook/src/stories/components/facepile.rs @@ -0,0 +1,69 @@ +use gpui2::elements::div; +use gpui2::style::StyleHelpers; +use gpui2::{rgb, Element, Hsla, IntoElement, ParentElement, ViewContext}; +use ui::{avatar, theme}; +use ui::{facepile, prelude::*}; + +#[derive(Element, Default)] +pub struct FacepileStory {} + +impl FacepileStory { + fn render(&mut self, _: &mut V, cx: &mut ViewContext) -> impl IntoElement { + let theme = theme(cx); + + div() + .size_full() + .flex() + .flex_col() + .pt_2() + .px_4() + .font("Zed Mono Extended") + .fill(rgb::(0x282c34)) + .child( + div() + .text_2xl() + .text_color(rgb::(0xffffff)) + .child(std::any::type_name::()), + ) + .child( + div() + .flex() + .gap_3() + .child(facepile(vec![avatar( + "https://avatars.githubusercontent.com/u/1714999?v=4", + )])) + .child(facepile(vec![ + avatar("https://avatars.githubusercontent.com/u/1714999?v=4"), + avatar("https://avatars.githubusercontent.com/u/1714999?v=4"), + ])) + .child(facepile(vec![ + avatar("https://avatars.githubusercontent.com/u/1714999?v=4"), + avatar("https://avatars.githubusercontent.com/u/1714999?v=4"), + avatar("https://avatars.githubusercontent.com/u/1714999?v=4"), + ])), + ) + .child( + div() + .flex() + .gap_3() + .child(facepile(vec![avatar( + "https://avatars.githubusercontent.com/u/1714999?v=4", + ) + .shape(Shape::RoundedRectangle)])) + .child(facepile(vec![ + avatar("https://avatars.githubusercontent.com/u/1714999?v=4") + .shape(Shape::RoundedRectangle), + avatar("https://avatars.githubusercontent.com/u/1714999?v=4") + .shape(Shape::RoundedRectangle), + ])) + .child(facepile(vec![ + avatar("https://avatars.githubusercontent.com/u/1714999?v=4") + .shape(Shape::RoundedRectangle), + avatar("https://avatars.githubusercontent.com/u/1714999?v=4") + .shape(Shape::RoundedRectangle), + avatar("https://avatars.githubusercontent.com/u/1714999?v=4") + .shape(Shape::RoundedRectangle), + ])), + ) + } +} diff --git a/crates/storybook/src/stories/elements.rs b/crates/storybook/src/stories/elements.rs new file mode 100644 index 0000000000..124369cf9d --- /dev/null +++ b/crates/storybook/src/stories/elements.rs @@ -0,0 +1 @@ +pub mod avatar; diff --git a/crates/storybook/src/stories/elements/avatar.rs b/crates/storybook/src/stories/elements/avatar.rs new file mode 100644 index 0000000000..3239dbec9c --- /dev/null +++ b/crates/storybook/src/stories/elements/avatar.rs @@ -0,0 +1,41 @@ +use gpui2::elements::div; +use gpui2::style::StyleHelpers; +use gpui2::{rgb, Element, Hsla, IntoElement, ParentElement, ViewContext}; +use ui::prelude::*; +use ui::{avatar, theme}; + +#[derive(Element, Default)] +pub struct AvatarStory {} + +impl AvatarStory { + fn render(&mut self, _: &mut V, cx: &mut ViewContext) -> impl IntoElement { + let theme = theme(cx); + + div() + .size_full() + .flex() + .flex_col() + .pt_2() + .px_4() + .font("Zed Mono Extended") + .fill(rgb::(0x282c34)) + .child( + div() + .text_2xl() + .text_color(rgb::(0xffffff)) + .child(std::any::type_name::()), + ) + .child( + div() + .flex() + .gap_3() + .child(avatar( + "https://avatars.githubusercontent.com/u/1714999?v=4", + )) + .child( + avatar("https://avatars.githubusercontent.com/u/1714999?v=4") + .shape(Shape::RoundedRectangle), + ), + ) + } +} diff --git a/crates/storybook/src/storybook.rs b/crates/storybook/src/storybook.rs index 92d178fad2..089ff33049 100644 --- a/crates/storybook/src/storybook.rs +++ b/crates/storybook/src/storybook.rs @@ -1,25 +1,66 @@ #![allow(dead_code, unused_variables)] +mod collab_panel; +mod stories; +mod workspace; + +use std::str::FromStr; + use ::theme as legacy_theme; -use gpui2::{serde_json, vec2f, view, Element, RectF, ViewContext, WindowBounds}; +use clap::Parser; +use gpui2::{serde_json, vec2f, view, Element, IntoElement, RectF, ViewContext, WindowBounds}; use legacy_theme::ThemeSettings; use log::LevelFilter; use settings::{default_settings, SettingsStore}; use simplelog::SimpleLogger; +use stories::components::facepile::FacepileStory; +use stories::elements::avatar::AvatarStory; use ui::{ElementExt, Theme}; -mod collab_panel; -mod workspace; - gpui2::actions! { storybook, [ToggleInspector] } +#[derive(Debug, Clone, Copy)] +enum Story { + Element(ElementStory), + Component(ComponentStory), +} + +impl FromStr for Story { + type Err = anyhow::Error; + + fn from_str(s: &str) -> std::result::Result { + match s.to_ascii_lowercase().as_str() { + "elements/avatar" => Ok(Self::Element(ElementStory::Avatar)), + "components/facepile" => Ok(Self::Component(ComponentStory::Facepile)), + _ => Err(anyhow!("story not found for '{s}'")), + } + } +} + +#[derive(Debug, Clone, Copy)] +enum ElementStory { + Avatar, +} + +#[derive(Debug, Clone, Copy)] +enum ComponentStory { + Facepile, +} + +#[derive(Parser)] +struct Args { + story: Option, +} + fn main() { SimpleLogger::init(LevelFilter::Info, Default::default()).expect("could not initialize logger"); - gpui2::App::new(Assets).unwrap().run(|cx| { + let args = Args::parse(); + + gpui2::App::new(Assets).unwrap().run(move |cx| { let mut store = SettingsStore::default(); store .set_default_settings(default_settings().as_ref(), cx) @@ -34,19 +75,27 @@ fn main() { center: true, ..Default::default() }, - |cx| { - view(|cx| { - // cx.enable_inspector(); - storybook(&mut ViewContext::new(cx)) - }) + |cx| match args.story { + Some(Story::Element(ElementStory::Avatar)) => { + view(|cx| render_story(&mut ViewContext::new(cx), AvatarStory::default())) + } + Some(Story::Component(ComponentStory::Facepile)) => { + view(|cx| render_story(&mut ViewContext::new(cx), FacepileStory::default())) + } + None => { + view(|cx| render_story(&mut ViewContext::new(cx), WorkspaceElement::default())) + } }, ); cx.platform().activate(true); }); } -fn storybook(cx: &mut ViewContext) -> impl Element { - workspace().themed(current_theme(cx)) +fn render_story>( + cx: &mut ViewContext, + story: S, +) -> impl Element { + story.into_element().themed(current_theme(cx)) } // Nathan: During the transition to gpui2, we will include the base theme on the legacy Theme struct. @@ -69,7 +118,7 @@ fn current_theme(cx: &mut ViewContext) -> Theme { use anyhow::{anyhow, Result}; use gpui2::AssetSource; use rust_embed::RustEmbed; -use workspace::workspace; +use workspace::WorkspaceElement; #[derive(RustEmbed)] #[folder = "../../assets"] diff --git a/crates/storybook/src/workspace.rs b/crates/storybook/src/workspace.rs index 95152ec832..58c5fed62d 100644 --- a/crates/storybook/src/workspace.rs +++ b/crates/storybook/src/workspace.rs @@ -6,16 +6,12 @@ use gpui2::{ use ui::{chat_panel, project_panel, status_bar, tab_bar, theme, title_bar}; #[derive(Element, Default)] -struct WorkspaceElement { +pub struct WorkspaceElement { left_scroll_state: ScrollState, right_scroll_state: ScrollState, tab_bar_scroll_state: ScrollState, } -pub fn workspace() -> impl Element { - WorkspaceElement::default() -} - impl WorkspaceElement { fn render(&mut self, _: &mut V, cx: &mut ViewContext) -> impl IntoElement { let theme = theme(cx);