diff --git a/Cargo.lock b/Cargo.lock index 4b2f9146b4..f5452ac2e0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -9060,6 +9060,7 @@ dependencies = [ "anyhow", "chrono", "gpui3", + "itertools 0.11.0", "rand 0.8.5", "serde", "settings", diff --git a/crates/storybook2/src/stories.rs b/crates/storybook2/src/stories.rs index 95b8844157..5df182e193 100644 --- a/crates/storybook2/src/stories.rs +++ b/crates/storybook2/src/stories.rs @@ -1,3 +1,2 @@ -pub mod components; pub mod elements; pub mod kitchen_sink; diff --git a/crates/storybook2/src/stories/components.rs b/crates/storybook2/src/stories/components.rs deleted file mode 100644 index 4c7db1bcdf..0000000000 --- a/crates/storybook2/src/stories/components.rs +++ /dev/null @@ -1,23 +0,0 @@ -pub mod breadcrumb; -pub mod buffer; -pub mod chat_panel; -pub mod collab_panel; -pub mod command_palette; -pub mod context_menu; -pub mod facepile; -pub mod keybinding; -pub mod language_selector; -pub mod multi_buffer; -pub mod palette; -pub mod panel; -pub mod project_panel; -pub mod recent_projects; -pub mod tab; -pub mod tab_bar; -pub mod terminal; -pub mod theme_selector; -pub mod title_bar; -pub mod toast; -pub mod toolbar; -pub mod traffic_lights; -pub mod workspace; diff --git a/crates/storybook2/src/stories/components/breadcrumb.rs b/crates/storybook2/src/stories/components/breadcrumb.rs deleted file mode 100644 index 48eed1f7ef..0000000000 --- a/crates/storybook2/src/stories/components/breadcrumb.rs +++ /dev/null @@ -1,54 +0,0 @@ -use std::marker::PhantomData; -use std::path::PathBuf; -use std::str::FromStr; - -use ui::prelude::*; -use ui::{Breadcrumb, HighlightedText, Symbol}; - -use crate::story::Story; - -#[derive(Element)] -pub struct BreadcrumbStory { - state_type: PhantomData, -} - -impl BreadcrumbStory { - pub fn new() -> Self { - Self { - state_type: PhantomData, - } - } - - fn render(&mut self, cx: &mut ViewContext) -> impl Element { - let theme = theme(cx); - - Story::container(cx) - .child(Story::title_for::<_, Breadcrumb>(cx)) - .child(Story::label(cx, "Default")) - .child(Breadcrumb::new( - PathBuf::from_str("crates/ui/src/components/toolbar.rs").unwrap(), - vec![ - Symbol(vec![ - HighlightedText { - text: "impl ".to_string(), - color: HighlightColor::Keyword.hsla(&theme), - }, - HighlightedText { - text: "BreadcrumbStory".to_string(), - color: HighlightColor::Function.hsla(&theme), - }, - ]), - Symbol(vec![ - HighlightedText { - text: "fn ".to_string(), - color: HighlightColor::Keyword.hsla(&theme), - }, - HighlightedText { - text: "render".to_string(), - color: HighlightColor::Function.hsla(&theme), - }, - ]), - ], - )) - } -} diff --git a/crates/storybook2/src/stories/components/buffer.rs b/crates/storybook2/src/stories/components/buffer.rs deleted file mode 100644 index d253b887e8..0000000000 --- a/crates/storybook2/src/stories/components/buffer.rs +++ /dev/null @@ -1,46 +0,0 @@ -use std::marker::PhantomData; - -use gpui3::rems; -use ui::prelude::*; -use ui::{ - empty_buffer_example, hello_world_rust_buffer_example, - hello_world_rust_buffer_with_status_example, Buffer, -}; - -use crate::story::Story; - -#[derive(Element)] -pub struct BufferStory { - state_type: PhantomData, -} - -impl BufferStory { - pub fn new() -> Self { - Self { - state_type: PhantomData, - } - } - - fn render(&mut self, cx: &mut ViewContext) -> impl Element { - let theme = theme(cx); - - Story::container(cx) - .child(Story::title_for::<_, Buffer>(cx)) - .child(Story::label(cx, "Default")) - .child(div().w(rems(64.)).h_96().child(empty_buffer_example())) - .child(Story::label(cx, "Hello World (Rust)")) - .child( - div() - .w(rems(64.)) - .h_96() - .child(hello_world_rust_buffer_example(&theme)), - ) - .child(Story::label(cx, "Hello World (Rust) with Status")) - .child( - div() - .w(rems(64.)) - .h_96() - .child(hello_world_rust_buffer_with_status_example(&theme)), - ) - } -} diff --git a/crates/storybook2/src/stories/components/chat_panel.rs b/crates/storybook2/src/stories/components/chat_panel.rs deleted file mode 100644 index cdf3f862c3..0000000000 --- a/crates/storybook2/src/stories/components/chat_panel.rs +++ /dev/null @@ -1,56 +0,0 @@ -use std::marker::PhantomData; - -use chrono::DateTime; -use ui::prelude::*; -use ui::{ChatMessage, ChatPanel, Panel}; - -use crate::story::Story; - -#[derive(Element)] -pub struct ChatPanelStory { - state_type: PhantomData, -} - -impl ChatPanelStory { - pub fn new() -> Self { - Self { - state_type: PhantomData, - } - } - - fn render(&mut self, cx: &mut ViewContext) -> impl Element { - Story::container(cx) - .child(Story::title_for::<_, ChatPanel>(cx)) - .child(Story::label(cx, "Default")) - .child(Panel::new( - ScrollState::default(), - |_, _| vec![ChatPanel::new(ScrollState::default()).into_any()], - Box::new(()), - )) - .child(Story::label(cx, "With Mesages")) - .child(Panel::new( - ScrollState::default(), - |_, _| { - vec![ChatPanel::new(ScrollState::default()) - .with_messages(vec![ - ChatMessage::new( - "osiewicz".to_string(), - "is this thing on?".to_string(), - DateTime::parse_from_rfc3339("2023-09-27T15:40:52.707Z") - .unwrap() - .naive_local(), - ), - ChatMessage::new( - "maxdeviant".to_string(), - "Reading you loud and clear!".to_string(), - DateTime::parse_from_rfc3339("2023-09-28T15:40:52.707Z") - .unwrap() - .naive_local(), - ), - ]) - .into_any()] - }, - Box::new(()), - )) - } -} diff --git a/crates/storybook2/src/stories/components/collab_panel.rs b/crates/storybook2/src/stories/components/collab_panel.rs deleted file mode 100644 index d1a3b072d7..0000000000 --- a/crates/storybook2/src/stories/components/collab_panel.rs +++ /dev/null @@ -1,26 +0,0 @@ -use std::marker::PhantomData; - -use ui::prelude::*; -use ui::CollabPanel; - -use crate::story::Story; - -#[derive(Element)] -pub struct CollabPanelStory { - state_type: PhantomData, -} - -impl CollabPanelStory { - pub fn new() -> Self { - Self { - state_type: PhantomData, - } - } - - fn render(&mut self, cx: &mut ViewContext) -> impl Element { - Story::container(cx) - .child(Story::title_for::<_, CollabPanel>(cx)) - .child(Story::label(cx, "Default")) - .child(CollabPanel::new(ScrollState::default())) - } -} diff --git a/crates/storybook2/src/stories/components/command_palette.rs b/crates/storybook2/src/stories/components/command_palette.rs deleted file mode 100644 index d3575cdb50..0000000000 --- a/crates/storybook2/src/stories/components/command_palette.rs +++ /dev/null @@ -1,26 +0,0 @@ -use std::marker::PhantomData; - -use ui::prelude::*; -use ui::CommandPalette; - -use crate::story::Story; - -#[derive(Element)] -pub struct CommandPaletteStory { - state_type: PhantomData, -} - -impl CommandPaletteStory { - pub fn new() -> Self { - Self { - state_type: PhantomData, - } - } - - fn render(&mut self, cx: &mut ViewContext) -> impl Element { - Story::container(cx) - .child(Story::title_for::<_, CommandPalette>(cx)) - .child(Story::label(cx, "Default")) - .child(CommandPalette::new(ScrollState::default())) - } -} diff --git a/crates/storybook2/src/stories/components/context_menu.rs b/crates/storybook2/src/stories/components/context_menu.rs deleted file mode 100644 index f93f97f133..0000000000 --- a/crates/storybook2/src/stories/components/context_menu.rs +++ /dev/null @@ -1,30 +0,0 @@ -use std::marker::PhantomData; - -use ui::prelude::*; -use ui::{ContextMenu, ContextMenuItem, Label}; - -use crate::story::Story; - -#[derive(Element)] -pub struct ContextMenuStory { - state_type: PhantomData, -} - -impl ContextMenuStory { - pub fn new() -> Self { - Self { - state_type: PhantomData, - } - } - - fn render(&mut self, cx: &mut ViewContext) -> impl Element { - Story::container(cx) - .child(Story::title_for::<_, ContextMenu>(cx)) - .child(Story::label(cx, "Default")) - .child(ContextMenu::new([ - ContextMenuItem::header("Section header"), - ContextMenuItem::Separator, - ContextMenuItem::entry(Label::new("Some entry")), - ])) - } -} diff --git a/crates/storybook2/src/stories/components/facepile.rs b/crates/storybook2/src/stories/components/facepile.rs deleted file mode 100644 index 54599e5e89..0000000000 --- a/crates/storybook2/src/stories/components/facepile.rs +++ /dev/null @@ -1,35 +0,0 @@ -use std::marker::PhantomData; - -use ui::prelude::*; -use ui::{static_players, Facepile}; - -use crate::story::Story; - -#[derive(Element)] -pub struct FacepileStory { - state_type: PhantomData, -} - -impl FacepileStory { - pub fn new() -> Self { - Self { - state_type: PhantomData, - } - } - - fn render(&mut self, cx: &mut ViewContext) -> impl Element { - let players = static_players(); - - Story::container(cx) - .child(Story::title_for::<_, Facepile>(cx)) - .child(Story::label(cx, "Default")) - .child( - div() - .flex() - .gap_3() - .child(Facepile::new(players.clone().into_iter().take(1))) - .child(Facepile::new(players.clone().into_iter().take(2))) - .child(Facepile::new(players.clone().into_iter().take(3))), - ) - } -} diff --git a/crates/storybook2/src/stories/components/keybinding.rs b/crates/storybook2/src/stories/components/keybinding.rs deleted file mode 100644 index 434a587cfc..0000000000 --- a/crates/storybook2/src/stories/components/keybinding.rs +++ /dev/null @@ -1,74 +0,0 @@ -use std::marker::PhantomData; - -use itertools::Itertools; -use strum::IntoEnumIterator; -use ui::prelude::*; -use ui::{Keybinding, ModifierKey, ModifierKeys}; - -use crate::story::Story; - -#[derive(Element)] -pub struct KeybindingStory { - state_type: PhantomData, -} - -impl KeybindingStory { - pub fn new() -> Self { - Self { - state_type: PhantomData, - } - } - - fn render(&mut self, cx: &mut ViewContext) -> impl Element { - let all_modifier_permutations = ModifierKey::iter().permutations(2); - - Story::container(cx) - .child(Story::title_for::<_, Keybinding>(cx)) - .child(Story::label(cx, "Single Key")) - .child(Keybinding::new("Z".to_string(), ModifierKeys::new())) - .child(Story::label(cx, "Single Key with Modifier")) - .child( - div() - .flex() - .gap_3() - .children(ModifierKey::iter().map(|modifier| { - Keybinding::new("C".to_string(), ModifierKeys::new().add(modifier)) - })), - ) - .child(Story::label(cx, "Single Key with Modifier (Permuted)")) - .child( - div().flex().flex_col().children( - all_modifier_permutations - .chunks(4) - .into_iter() - .map(|chunk| { - div() - .flex() - .gap_4() - .py_3() - .children(chunk.map(|permutation| { - let mut modifiers = ModifierKeys::new(); - - for modifier in permutation { - modifiers = modifiers.add(modifier); - } - - Keybinding::new("X".to_string(), modifiers) - })) - }), - ), - ) - .child(Story::label(cx, "Single Key with All Modifiers")) - .child(Keybinding::new("Z".to_string(), ModifierKeys::all())) - .child(Story::label(cx, "Chord")) - .child(Keybinding::new_chord( - ("A".to_string(), ModifierKeys::new()), - ("Z".to_string(), ModifierKeys::new()), - )) - .child(Story::label(cx, "Chord with Modifier")) - .child(Keybinding::new_chord( - ("A".to_string(), ModifierKeys::new().control(true)), - ("Z".to_string(), ModifierKeys::new().shift(true)), - )) - } -} diff --git a/crates/storybook2/src/stories/components/language_selector.rs b/crates/storybook2/src/stories/components/language_selector.rs deleted file mode 100644 index cd167658dc..0000000000 --- a/crates/storybook2/src/stories/components/language_selector.rs +++ /dev/null @@ -1,26 +0,0 @@ -use std::marker::PhantomData; - -use ui::prelude::*; -use ui::LanguageSelector; - -use crate::story::Story; - -#[derive(Element)] -pub struct LanguageSelectorStory { - state_type: PhantomData, -} - -impl LanguageSelectorStory { - pub fn new() -> Self { - Self { - state_type: PhantomData, - } - } - - fn render(&mut self, cx: &mut ViewContext) -> impl Element { - Story::container(cx) - .child(Story::title_for::<_, LanguageSelector>(cx)) - .child(Story::label(cx, "Default")) - .child(LanguageSelector::new()) - } -} diff --git a/crates/storybook2/src/stories/components/multi_buffer.rs b/crates/storybook2/src/stories/components/multi_buffer.rs deleted file mode 100644 index d4b0c7fdb5..0000000000 --- a/crates/storybook2/src/stories/components/multi_buffer.rs +++ /dev/null @@ -1,34 +0,0 @@ -use std::marker::PhantomData; - -use ui::prelude::*; -use ui::{hello_world_rust_buffer_example, MultiBuffer}; - -use crate::story::Story; - -#[derive(Element)] -pub struct MultiBufferStory { - state_type: PhantomData, -} - -impl MultiBufferStory { - pub fn new() -> Self { - Self { - state_type: PhantomData, - } - } - - fn render(&mut self, cx: &mut ViewContext) -> impl Element { - let theme = theme(cx); - - Story::container(cx) - .child(Story::title_for::<_, MultiBuffer>(cx)) - .child(Story::label(cx, "Default")) - .child(MultiBuffer::new(vec![ - hello_world_rust_buffer_example(&theme), - hello_world_rust_buffer_example(&theme), - hello_world_rust_buffer_example(&theme), - hello_world_rust_buffer_example(&theme), - hello_world_rust_buffer_example(&theme), - ])) - } -} diff --git a/crates/storybook2/src/stories/components/palette.rs b/crates/storybook2/src/stories/components/palette.rs deleted file mode 100644 index 1cdbd995a6..0000000000 --- a/crates/storybook2/src/stories/components/palette.rs +++ /dev/null @@ -1,63 +0,0 @@ -use std::marker::PhantomData; - -use ui::prelude::*; -use ui::{Keybinding, ModifierKeys, Palette, PaletteItem}; - -use crate::story::Story; - -#[derive(Element)] -pub struct PaletteStory { - state_type: PhantomData, -} - -impl PaletteStory { - pub fn new() -> Self { - Self { - state_type: PhantomData, - } - } - - fn render(&mut self, cx: &mut ViewContext) -> impl Element { - Story::container(cx) - .child(Story::title_for::<_, Palette>(cx)) - .child(Story::label(cx, "Default")) - .child(Palette::new(ScrollState::default())) - .child(Story::label(cx, "With Items")) - .child( - Palette::new(ScrollState::default()) - .placeholder("Execute a command...") - .items(vec![ - PaletteItem::new("theme selector: toggle").keybinding( - Keybinding::new_chord( - ("k".to_string(), ModifierKeys::new().command(true)), - ("t".to_string(), ModifierKeys::new().command(true)), - ), - ), - PaletteItem::new("assistant: inline assist").keybinding(Keybinding::new( - "enter".to_string(), - ModifierKeys::new().command(true), - )), - PaletteItem::new("assistant: quote selection").keybinding(Keybinding::new( - ">".to_string(), - ModifierKeys::new().command(true), - )), - PaletteItem::new("assistant: toggle focus").keybinding(Keybinding::new( - "?".to_string(), - ModifierKeys::new().command(true), - )), - PaletteItem::new("auto update: check"), - PaletteItem::new("auto update: view release notes"), - PaletteItem::new("branches: open recent").keybinding(Keybinding::new( - "b".to_string(), - ModifierKeys::new().command(true).alt(true), - )), - PaletteItem::new("chat panel: toggle focus"), - PaletteItem::new("cli: install"), - PaletteItem::new("client: sign in"), - PaletteItem::new("client: sign out"), - PaletteItem::new("editor: cancel") - .keybinding(Keybinding::new("escape".to_string(), ModifierKeys::new())), - ]), - ) - } -} diff --git a/crates/storybook2/src/stories/components/panel.rs b/crates/storybook2/src/stories/components/panel.rs deleted file mode 100644 index 9470bda4bd..0000000000 --- a/crates/storybook2/src/stories/components/panel.rs +++ /dev/null @@ -1,35 +0,0 @@ -use std::marker::PhantomData; - -use ui::prelude::*; -use ui::{Label, Panel}; - -use crate::story::Story; - -#[derive(Element)] -pub struct PanelStory { - state_type: PhantomData, -} - -impl PanelStory { - pub fn new() -> Self { - Self { - state_type: PhantomData, - } - } - - fn render(&mut self, cx: &mut ViewContext) -> impl Element { - Story::container(cx) - .child(Story::title_for::<_, Panel>(cx)) - .child(Story::label(cx, "Default")) - .child(Panel::new( - ScrollState::default(), - |_, _| { - vec![div() - .overflow_y_scroll(ScrollState::default()) - .children((0..100).map(|ix| Label::new(format!("Item {}", ix + 1)))) - .into_any()] - }, - Box::new(()), - )) - } -} diff --git a/crates/storybook2/src/stories/components/project_panel.rs b/crates/storybook2/src/stories/components/project_panel.rs deleted file mode 100644 index c2fb4edd49..0000000000 --- a/crates/storybook2/src/stories/components/project_panel.rs +++ /dev/null @@ -1,30 +0,0 @@ -use std::marker::PhantomData; - -use ui::prelude::*; -use ui::{Panel, ProjectPanel}; - -use crate::story::Story; - -#[derive(Element)] -pub struct ProjectPanelStory { - state_type: PhantomData, -} - -impl ProjectPanelStory { - pub fn new() -> Self { - Self { - state_type: PhantomData, - } - } - - fn render(&mut self, cx: &mut ViewContext) -> impl Element { - Story::container(cx) - .child(Story::title_for::<_, ProjectPanel>(cx)) - .child(Story::label(cx, "Default")) - .child(Panel::new( - ScrollState::default(), - |_, _| vec![ProjectPanel::new(ScrollState::default()).into_any()], - Box::new(()), - )) - } -} diff --git a/crates/storybook2/src/stories/components/recent_projects.rs b/crates/storybook2/src/stories/components/recent_projects.rs deleted file mode 100644 index d347092f79..0000000000 --- a/crates/storybook2/src/stories/components/recent_projects.rs +++ /dev/null @@ -1,26 +0,0 @@ -use std::marker::PhantomData; - -use ui::prelude::*; -use ui::RecentProjects; - -use crate::story::Story; - -#[derive(Element)] -pub struct RecentProjectsStory { - state_type: PhantomData, -} - -impl RecentProjectsStory { - pub fn new() -> Self { - Self { - state_type: PhantomData, - } - } - - fn render(&mut self, cx: &mut ViewContext) -> impl Element { - Story::container(cx) - .child(Story::title_for::<_, RecentProjects>(cx)) - .child(Story::label(cx, "Default")) - .child(RecentProjects::new()) - } -} diff --git a/crates/storybook2/src/stories/components/tab.rs b/crates/storybook2/src/stories/components/tab.rs deleted file mode 100644 index d2435d780b..0000000000 --- a/crates/storybook2/src/stories/components/tab.rs +++ /dev/null @@ -1,101 +0,0 @@ -use std::marker::PhantomData; - -use strum::IntoEnumIterator; -use ui::prelude::*; -use ui::{h_stack, v_stack, Tab}; - -use crate::story::Story; - -#[derive(Element)] -pub struct TabStory { - state_type: PhantomData, -} - -impl TabStory { - pub fn new() -> Self { - Self { - state_type: PhantomData, - } - } - - fn render(&mut self, cx: &mut ViewContext) -> impl Element { - let git_statuses = GitStatus::iter(); - let fs_statuses = FileSystemStatus::iter(); - - Story::container(cx) - .child(Story::title_for::<_, Tab>(cx)) - .child( - h_stack().child( - v_stack() - .gap_2() - .child(Story::label(cx, "Default")) - .child(Tab::new()), - ), - ) - .child( - h_stack().child( - v_stack().gap_2().child(Story::label(cx, "Current")).child( - h_stack() - .gap_4() - .child(Tab::new().title("Current".to_string()).current(true)) - .child(Tab::new().title("Not Current".to_string()).current(false)), - ), - ), - ) - .child( - h_stack().child( - v_stack() - .gap_2() - .child(Story::label(cx, "Titled")) - .child(Tab::new().title("label".to_string())), - ), - ) - .child( - h_stack().child( - v_stack() - .gap_2() - .child(Story::label(cx, "With Icon")) - .child( - Tab::new() - .title("label".to_string()) - .icon(Some(ui::Icon::Envelope)), - ), - ), - ) - .child( - h_stack().child( - v_stack() - .gap_2() - .child(Story::label(cx, "Close Side")) - .child( - h_stack() - .gap_4() - .child( - Tab::new() - .title("Left".to_string()) - .close_side(IconSide::Left), - ) - .child(Tab::new().title("Right".to_string())), - ), - ), - ) - .child( - v_stack() - .gap_2() - .child(Story::label(cx, "Git Status")) - .child(h_stack().gap_4().children(git_statuses.map(|git_status| { - Tab::new() - .title(git_status.to_string()) - .git_status(git_status) - }))), - ) - .child( - v_stack() - .gap_2() - .child(Story::label(cx, "File System Status")) - .child(h_stack().gap_4().children(fs_statuses.map(|fs_status| { - Tab::new().title(fs_status.to_string()).fs_status(fs_status) - }))), - ) - } -} diff --git a/crates/storybook2/src/stories/components/tab_bar.rs b/crates/storybook2/src/stories/components/tab_bar.rs deleted file mode 100644 index d3461418b3..0000000000 --- a/crates/storybook2/src/stories/components/tab_bar.rs +++ /dev/null @@ -1,56 +0,0 @@ -use std::marker::PhantomData; - -use ui::prelude::*; -use ui::{Tab, TabBar}; - -use crate::story::Story; - -#[derive(Element)] -pub struct TabBarStory { - state_type: PhantomData, -} - -impl TabBarStory { - pub fn new() -> Self { - Self { - state_type: PhantomData, - } - } - - fn render(&mut self, cx: &mut ViewContext) -> impl Element { - Story::container(cx) - .child(Story::title_for::<_, TabBar>(cx)) - .child(Story::label(cx, "Default")) - .child(TabBar::new(vec![ - Tab::new() - .title("Cargo.toml".to_string()) - .current(false) - .git_status(GitStatus::Modified), - Tab::new() - .title("Channels Panel".to_string()) - .current(false), - Tab::new() - .title("channels_panel.rs".to_string()) - .current(true) - .git_status(GitStatus::Modified), - Tab::new() - .title("workspace.rs".to_string()) - .current(false) - .git_status(GitStatus::Modified), - Tab::new() - .title("icon_button.rs".to_string()) - .current(false), - Tab::new() - .title("storybook.rs".to_string()) - .current(false) - .git_status(GitStatus::Created), - Tab::new().title("theme.rs".to_string()).current(false), - Tab::new() - .title("theme_registry.rs".to_string()) - .current(false), - Tab::new() - .title("styleable_helpers.rs".to_string()) - .current(false), - ])) - } -} diff --git a/crates/storybook2/src/stories/components/terminal.rs b/crates/storybook2/src/stories/components/terminal.rs deleted file mode 100644 index 6a63306ed9..0000000000 --- a/crates/storybook2/src/stories/components/terminal.rs +++ /dev/null @@ -1,26 +0,0 @@ -use std::marker::PhantomData; - -use ui::prelude::*; -use ui::Terminal; - -use crate::story::Story; - -#[derive(Element)] -pub struct TerminalStory { - state_type: PhantomData, -} - -impl TerminalStory { - pub fn new() -> Self { - Self { - state_type: PhantomData, - } - } - - fn render(&mut self, cx: &mut ViewContext) -> impl Element { - Story::container(cx) - .child(Story::title_for::<_, Terminal>(cx)) - .child(Story::label(cx, "Default")) - .child(Terminal::new()) - } -} diff --git a/crates/storybook2/src/stories/components/theme_selector.rs b/crates/storybook2/src/stories/components/theme_selector.rs deleted file mode 100644 index b766a9afac..0000000000 --- a/crates/storybook2/src/stories/components/theme_selector.rs +++ /dev/null @@ -1,26 +0,0 @@ -use std::marker::PhantomData; - -use ui::prelude::*; -use ui::ThemeSelector; - -use crate::story::Story; - -#[derive(Element)] -pub struct ThemeSelectorStory { - state_type: PhantomData, -} - -impl ThemeSelectorStory { - pub fn new() -> Self { - Self { - state_type: PhantomData, - } - } - - fn render(&mut self, cx: &mut ViewContext) -> impl Element { - Story::container(cx) - .child(Story::title_for::<_, ThemeSelector>(cx)) - .child(Story::label(cx, "Default")) - .child(ThemeSelector::new()) - } -} diff --git a/crates/storybook2/src/stories/components/title_bar.rs b/crates/storybook2/src/stories/components/title_bar.rs deleted file mode 100644 index b0cf2cd771..0000000000 --- a/crates/storybook2/src/stories/components/title_bar.rs +++ /dev/null @@ -1,26 +0,0 @@ -use std::marker::PhantomData; - -use ui::prelude::*; -use ui::TitleBar; - -use crate::story::Story; - -#[derive(Element)] -pub struct TitleBarStory { - state_type: PhantomData, -} - -impl TitleBarStory { - pub fn new() -> Self { - Self { - state_type: PhantomData, - } - } - - fn render(&mut self, cx: &mut ViewContext) -> impl Element { - Story::container(cx) - .child(Story::title_for::<_, TitleBar>(cx)) - .child(Story::label(cx, "Default")) - .child(TitleBar::new(cx)) - } -} diff --git a/crates/storybook2/src/stories/components/toast.rs b/crates/storybook2/src/stories/components/toast.rs deleted file mode 100644 index 65cf4abde8..0000000000 --- a/crates/storybook2/src/stories/components/toast.rs +++ /dev/null @@ -1,30 +0,0 @@ -use std::marker::PhantomData; - -use ui::prelude::*; -use ui::{Label, Toast, ToastOrigin}; - -use crate::story::Story; - -#[derive(Element)] -pub struct ToastStory { - state_type: PhantomData, -} - -impl ToastStory { - pub fn new() -> Self { - Self { - state_type: PhantomData, - } - } - - fn render(&mut self, cx: &mut ViewContext) -> impl Element { - Story::container(cx) - .child(Story::title_for::<_, Toast>(cx)) - .child(Story::label(cx, "Default")) - .child(Toast::new( - ToastOrigin::Bottom, - |_, _| vec![Label::new("label").into_any()], - Box::new(()), - )) - } -} diff --git a/crates/storybook2/src/stories/components/toolbar.rs b/crates/storybook2/src/stories/components/toolbar.rs deleted file mode 100644 index 451ce76aab..0000000000 --- a/crates/storybook2/src/stories/components/toolbar.rs +++ /dev/null @@ -1,79 +0,0 @@ -use std::marker::PhantomData; -use std::path::PathBuf; -use std::str::FromStr; -use std::sync::Arc; - -use ui::prelude::*; -use ui::{theme, Breadcrumb, HighlightColor, HighlightedText, Icon, IconButton, Symbol, Toolbar}; - -use crate::story::Story; - -#[derive(Element)] -pub struct ToolbarStory { - state_type: PhantomData, -} - -impl ToolbarStory { - pub fn new() -> Self { - Self { - state_type: PhantomData, - } - } - - fn render(&mut self, cx: &mut ViewContext) -> impl Element { - let theme = theme(cx); - - struct LeftItemsPayload { - pub theme: Arc, - } - - Story::container(cx) - .child(Story::title_for::<_, Toolbar>(cx)) - .child(Story::label(cx, "Default")) - .child(Toolbar::new( - |_, payload| { - let payload = payload.downcast_ref::().unwrap(); - - let theme = payload.theme.clone(); - - vec![Breadcrumb::new( - PathBuf::from_str("crates/ui/src/components/toolbar.rs").unwrap(), - vec![ - Symbol(vec![ - HighlightedText { - text: "impl ".to_string(), - color: HighlightColor::Keyword.hsla(&theme), - }, - HighlightedText { - text: "ToolbarStory".to_string(), - color: HighlightColor::Function.hsla(&theme), - }, - ]), - Symbol(vec![ - HighlightedText { - text: "fn ".to_string(), - color: HighlightColor::Keyword.hsla(&theme), - }, - HighlightedText { - text: "render".to_string(), - color: HighlightColor::Function.hsla(&theme), - }, - ]), - ], - ) - .into_any()] - }, - Box::new(LeftItemsPayload { - theme: theme.clone(), - }), - |_, _| { - vec![ - IconButton::new(Icon::InlayHint).into_any(), - IconButton::new(Icon::MagnifyingGlass).into_any(), - IconButton::new(Icon::MagicWand).into_any(), - ] - }, - Box::new(()), - )) - } -} diff --git a/crates/storybook2/src/stories/components/traffic_lights.rs b/crates/storybook2/src/stories/components/traffic_lights.rs deleted file mode 100644 index 056e258aaa..0000000000 --- a/crates/storybook2/src/stories/components/traffic_lights.rs +++ /dev/null @@ -1,28 +0,0 @@ -use std::marker::PhantomData; - -use ui::prelude::*; -use ui::TrafficLights; - -use crate::story::Story; - -#[derive(Element)] -pub struct TrafficLightsStory { - state_type: PhantomData, -} - -impl TrafficLightsStory { - pub fn new() -> Self { - Self { - state_type: PhantomData, - } - } - - fn render(&mut self, cx: &mut ViewContext) -> impl Element { - Story::container(cx) - .child(Story::title_for::<_, TrafficLights>(cx)) - .child(Story::label(cx, "Default")) - .child(TrafficLights::new()) - .child(Story::label(cx, "Unfocused")) - .child(TrafficLights::new().window_has_focus(false)) - } -} diff --git a/crates/storybook2/src/stories/components/workspace.rs b/crates/storybook2/src/stories/components/workspace.rs deleted file mode 100644 index e9d8b4ace2..0000000000 --- a/crates/storybook2/src/stories/components/workspace.rs +++ /dev/null @@ -1,22 +0,0 @@ -use std::marker::PhantomData; - -use ui::prelude::*; -use ui::WorkspaceElement; - -#[derive(Element)] -pub struct WorkspaceStory { - state_type: PhantomData, -} - -impl WorkspaceStory { - pub fn new() -> Self { - Self { - state_type: PhantomData, - } - } - - fn render(&mut self, cx: &mut ViewContext) -> impl Element { - // Just render the workspace without any story boilerplate. - WorkspaceElement::new() - } -} diff --git a/crates/storybook2/src/story_selector.rs b/crates/storybook2/src/story_selector.rs index 9ee9272eda..a2aeab3ced 100644 --- a/crates/storybook2/src/story_selector.rs +++ b/crates/storybook2/src/story_selector.rs @@ -68,39 +68,31 @@ pub enum ComponentStory { impl ComponentStory { pub fn story(&self) -> AnyElement { - use crate::stories::components; - match self { Self::AssistantPanel => ui::AssistantPanelStory::new().into_any(), - Self::Buffer => components::buffer::BufferStory::new().into_any(), - Self::Breadcrumb => components::breadcrumb::BreadcrumbStory::new().into_any(), - Self::ChatPanel => components::chat_panel::ChatPanelStory::new().into_any(), - Self::CollabPanel => components::collab_panel::CollabPanelStory::new().into_any(), - Self::CommandPalette => { - components::command_palette::CommandPaletteStory::new().into_any() - } - Self::ContextMenu => components::context_menu::ContextMenuStory::new().into_any(), - Self::Facepile => components::facepile::FacepileStory::new().into_any(), - Self::Keybinding => components::keybinding::KeybindingStory::new().into_any(), - Self::LanguageSelector => { - components::language_selector::LanguageSelectorStory::new().into_any() - } - Self::MultiBuffer => components::multi_buffer::MultiBufferStory::new().into_any(), - 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(), - Self::ThemeSelector => components::theme_selector::ThemeSelectorStory::new().into_any(), - Self::TitleBar => components::title_bar::TitleBarStory::new().into_any(), - Self::Toast => components::toast::ToastStory::new().into_any(), - Self::Toolbar => components::toolbar::ToolbarStory::new().into_any(), - Self::TrafficLights => components::traffic_lights::TrafficLightsStory::new().into_any(), - Self::Workspace => components::workspace::WorkspaceStory::new().into_any(), + Self::Buffer => ui::BufferStory::new().into_any(), + Self::Breadcrumb => ui::BreadcrumbStory::new().into_any(), + Self::ChatPanel => ui::ChatPanelStory::new().into_any(), + Self::CollabPanel => ui::CollabPanelStory::new().into_any(), + Self::CommandPalette => ui::CommandPaletteStory::new().into_any(), + Self::ContextMenu => ui::ContextMenuStory::new().into_any(), + Self::Facepile => ui::FacepileStory::new().into_any(), + Self::Keybinding => ui::KeybindingStory::new().into_any(), + Self::LanguageSelector => ui::LanguageSelectorStory::new().into_any(), + Self::MultiBuffer => ui::MultiBufferStory::new().into_any(), + Self::Palette => ui::PaletteStory::new().into_any(), + Self::Panel => ui::PanelStory::new().into_any(), + Self::ProjectPanel => ui::ProjectPanelStory::new().into_any(), + Self::RecentProjects => ui::RecentProjectsStory::new().into_any(), + Self::Tab => ui::TabStory::new().into_any(), + Self::TabBar => ui::TabBarStory::new().into_any(), + Self::Terminal => ui::TerminalStory::new().into_any(), + Self::ThemeSelector => ui::ThemeSelectorStory::new().into_any(), + Self::TitleBar => ui::TitleBarStory::new().into_any(), + Self::Toast => ui::ToastStory::new().into_any(), + Self::Toolbar => ui::ToolbarStory::new().into_any(), + Self::TrafficLights => ui::TrafficLightsStory::new().into_any(), + Self::Workspace => ui::WorkspaceStory::new().into_any(), } } } diff --git a/crates/ui2/Cargo.toml b/crates/ui2/Cargo.toml index 248abcd387..3fe37da8fc 100644 --- a/crates/ui2/Cargo.toml +++ b/crates/ui2/Cargo.toml @@ -8,6 +8,7 @@ publish = false anyhow.workspace = true chrono = "0.4" gpui3 = { path = "../gpui3" } +itertools = { version = "0.11.0", optional = true } serde.workspace = true settings = { path = "../settings" } smallvec.workspace = true @@ -17,4 +18,4 @@ rand = "0.8" [features] default = ["stories"] -stories = [] +stories = ["dep:itertools"] diff --git a/crates/ui2/src/components/assistant_panel.rs b/crates/ui2/src/components/assistant_panel.rs index 8fa9922cc0..def22af18b 100644 --- a/crates/ui2/src/components/assistant_panel.rs +++ b/crates/ui2/src/components/assistant_panel.rs @@ -94,7 +94,7 @@ pub use stories::*; #[cfg(feature = "stories")] mod stories { - use crate::story::Story; + use crate::Story; use super::*; diff --git a/crates/ui2/src/components/breadcrumb.rs b/crates/ui2/src/components/breadcrumb.rs index c0760ef802..8572859c31 100644 --- a/crates/ui2/src/components/breadcrumb.rs +++ b/crates/ui2/src/components/breadcrumb.rs @@ -75,3 +75,61 @@ impl Breadcrumb { ) } } + +#[cfg(feature = "stories")] +pub use stories::*; + +#[cfg(feature = "stories")] +mod stories { + use std::str::FromStr; + + use crate::Story; + + use super::*; + + #[derive(Element)] + pub struct BreadcrumbStory { + state_type: PhantomData, + } + + impl BreadcrumbStory { + pub fn new() -> Self { + Self { + state_type: PhantomData, + } + } + + fn render(&mut self, cx: &mut ViewContext) -> impl Element { + let theme = theme(cx); + + Story::container(cx) + .child(Story::title_for::<_, Breadcrumb>(cx)) + .child(Story::label(cx, "Default")) + .child(Breadcrumb::new( + PathBuf::from_str("crates/ui/src/components/toolbar.rs").unwrap(), + vec![ + Symbol(vec![ + HighlightedText { + text: "impl ".to_string(), + color: HighlightColor::Keyword.hsla(&theme), + }, + HighlightedText { + text: "BreadcrumbStory".to_string(), + color: HighlightColor::Function.hsla(&theme), + }, + ]), + Symbol(vec![ + HighlightedText { + text: "fn ".to_string(), + color: HighlightColor::Keyword.hsla(&theme), + }, + HighlightedText { + text: "render".to_string(), + color: HighlightColor::Function.hsla(&theme), + }, + ]), + ], + )) + } + } +} diff --git a/crates/ui2/src/components/buffer.rs b/crates/ui2/src/components/buffer.rs index d753202841..89ecad19db 100644 --- a/crates/ui2/src/components/buffer.rs +++ b/crates/ui2/src/components/buffer.rs @@ -236,3 +236,54 @@ impl Buffer { .children(rows) } } + +#[cfg(feature = "stories")] +pub use stories::*; + +#[cfg(feature = "stories")] +mod stories { + use gpui3::rems; + + use crate::{ + empty_buffer_example, hello_world_rust_buffer_example, + hello_world_rust_buffer_with_status_example, Story, + }; + + use super::*; + + #[derive(Element)] + pub struct BufferStory { + state_type: PhantomData, + } + + impl BufferStory { + pub fn new() -> Self { + Self { + state_type: PhantomData, + } + } + + fn render(&mut self, cx: &mut ViewContext) -> impl Element { + let theme = theme(cx); + + Story::container(cx) + .child(Story::title_for::<_, Buffer>(cx)) + .child(Story::label(cx, "Default")) + .child(div().w(rems(64.)).h_96().child(empty_buffer_example())) + .child(Story::label(cx, "Hello World (Rust)")) + .child( + div() + .w(rems(64.)) + .h_96() + .child(hello_world_rust_buffer_example(&theme)), + ) + .child(Story::label(cx, "Hello World (Rust) with Status")) + .child( + div() + .w(rems(64.)) + .h_96() + .child(hello_world_rust_buffer_with_status_example(&theme)), + ) + } + } +} diff --git a/crates/ui2/src/components/chat_panel.rs b/crates/ui2/src/components/chat_panel.rs index e0cdd3382d..ab4f5853ce 100644 --- a/crates/ui2/src/components/chat_panel.rs +++ b/crates/ui2/src/components/chat_panel.rs @@ -106,3 +106,64 @@ impl ChatMessage { .child(div().child(Label::new(self.text.clone()))) } } + +#[cfg(feature = "stories")] +pub use stories::*; + +#[cfg(feature = "stories")] +mod stories { + use chrono::DateTime; + + use crate::{Panel, Story}; + + use super::*; + + #[derive(Element)] + pub struct ChatPanelStory { + state_type: PhantomData, + } + + impl ChatPanelStory { + pub fn new() -> Self { + Self { + state_type: PhantomData, + } + } + + fn render(&mut self, cx: &mut ViewContext) -> impl Element { + Story::container(cx) + .child(Story::title_for::<_, ChatPanel>(cx)) + .child(Story::label(cx, "Default")) + .child(Panel::new( + ScrollState::default(), + |_, _| vec![ChatPanel::new(ScrollState::default()).into_any()], + Box::new(()), + )) + .child(Story::label(cx, "With Mesages")) + .child(Panel::new( + ScrollState::default(), + |_, _| { + vec![ChatPanel::new(ScrollState::default()) + .with_messages(vec![ + ChatMessage::new( + "osiewicz".to_string(), + "is this thing on?".to_string(), + DateTime::parse_from_rfc3339("2023-09-27T15:40:52.707Z") + .unwrap() + .naive_local(), + ), + ChatMessage::new( + "maxdeviant".to_string(), + "Reading you loud and clear!".to_string(), + DateTime::parse_from_rfc3339("2023-09-28T15:40:52.707Z") + .unwrap() + .naive_local(), + ), + ]) + .into_any()] + }, + Box::new(()), + )) + } + } +} diff --git a/crates/ui2/src/components/collab_panel.rs b/crates/ui2/src/components/collab_panel.rs index 5a0098939a..991101fb13 100644 --- a/crates/ui2/src/components/collab_panel.rs +++ b/crates/ui2/src/components/collab_panel.rs @@ -158,3 +158,33 @@ impl CollabPanel { ) } } + +#[cfg(feature = "stories")] +pub use stories::*; + +#[cfg(feature = "stories")] +mod stories { + use crate::Story; + + use super::*; + + #[derive(Element)] + pub struct CollabPanelStory { + state_type: PhantomData, + } + + impl CollabPanelStory { + pub fn new() -> Self { + Self { + state_type: PhantomData, + } + } + + fn render(&mut self, cx: &mut ViewContext) -> impl Element { + Story::container(cx) + .child(Story::title_for::<_, CollabPanel>(cx)) + .child(Story::label(cx, "Default")) + .child(CollabPanel::new(ScrollState::default())) + } + } +} diff --git a/crates/ui2/src/components/command_palette.rs b/crates/ui2/src/components/command_palette.rs index 61e20d8535..6c29a787f5 100644 --- a/crates/ui2/src/components/command_palette.rs +++ b/crates/ui2/src/components/command_palette.rs @@ -27,3 +27,33 @@ impl CommandPalette { ) } } + +#[cfg(feature = "stories")] +pub use stories::*; + +#[cfg(feature = "stories")] +mod stories { + use crate::Story; + + use super::*; + + #[derive(Element)] + pub struct CommandPaletteStory { + state_type: PhantomData, + } + + impl CommandPaletteStory { + pub fn new() -> Self { + Self { + state_type: PhantomData, + } + } + + fn render(&mut self, cx: &mut ViewContext) -> impl Element { + Story::container(cx) + .child(Story::title_for::<_, CommandPalette>(cx)) + .child(Story::label(cx, "Default")) + .child(CommandPalette::new(ScrollState::default())) + } + } +} diff --git a/crates/ui2/src/components/context_menu.rs b/crates/ui2/src/components/context_menu.rs index 9fa7e7c635..ab02628816 100644 --- a/crates/ui2/src/components/context_menu.rs +++ b/crates/ui2/src/components/context_menu.rs @@ -65,3 +65,39 @@ impl ContextMenu { ) } } + +#[cfg(feature = "stories")] +pub use stories::*; + +#[cfg(feature = "stories")] +mod stories { + use std::marker::PhantomData; + + use crate::story::Story; + + use super::*; + + #[derive(Element)] + pub struct ContextMenuStory { + state_type: PhantomData, + } + + impl ContextMenuStory { + pub fn new() -> Self { + Self { + state_type: PhantomData, + } + } + + fn render(&mut self, cx: &mut ViewContext) -> impl Element { + Story::container(cx) + .child(Story::title_for::<_, ContextMenu>(cx)) + .child(Story::label(cx, "Default")) + .child(ContextMenu::new([ + ContextMenuItem::header("Section header"), + ContextMenuItem::Separator, + ContextMenuItem::entry(Label::new("Some entry")), + ])) + } + } +} diff --git a/crates/ui2/src/components/facepile.rs b/crates/ui2/src/components/facepile.rs index b7f1f78216..3a0aa055c2 100644 --- a/crates/ui2/src/components/facepile.rs +++ b/crates/ui2/src/components/facepile.rs @@ -30,3 +30,42 @@ impl Facepile { div().p_1().flex().items_center().children(player_list) } } + +#[cfg(feature = "stories")] +pub use stories::*; + +#[cfg(feature = "stories")] +mod stories { + use crate::{static_players, Story}; + + use super::*; + + #[derive(Element)] + pub struct FacepileStory { + state_type: PhantomData, + } + + impl FacepileStory { + pub fn new() -> Self { + Self { + state_type: PhantomData, + } + } + + fn render(&mut self, cx: &mut ViewContext) -> impl Element { + let players = static_players(); + + Story::container(cx) + .child(Story::title_for::<_, Facepile>(cx)) + .child(Story::label(cx, "Default")) + .child( + div() + .flex() + .gap_3() + .child(Facepile::new(players.clone().into_iter().take(1))) + .child(Facepile::new(players.clone().into_iter().take(2))) + .child(Facepile::new(players.clone().into_iter().take(3))), + ) + } + } +} diff --git a/crates/ui2/src/components/keybinding.rs b/crates/ui2/src/components/keybinding.rs index e516ad177f..3830d1a3e5 100644 --- a/crates/ui2/src/components/keybinding.rs +++ b/crates/ui2/src/components/keybinding.rs @@ -165,3 +165,81 @@ impl ModifierKeys { self } } + +#[cfg(feature = "stories")] +pub use stories::*; + +#[cfg(feature = "stories")] +mod stories { + use itertools::Itertools; + + use crate::Story; + + use super::*; + + #[derive(Element)] + pub struct KeybindingStory { + state_type: PhantomData, + } + + impl KeybindingStory { + pub fn new() -> Self { + Self { + state_type: PhantomData, + } + } + + fn render(&mut self, cx: &mut ViewContext) -> impl Element { + let all_modifier_permutations = ModifierKey::iter().permutations(2); + + Story::container(cx) + .child(Story::title_for::<_, Keybinding>(cx)) + .child(Story::label(cx, "Single Key")) + .child(Keybinding::new("Z".to_string(), ModifierKeys::new())) + .child(Story::label(cx, "Single Key with Modifier")) + .child( + div() + .flex() + .gap_3() + .children(ModifierKey::iter().map(|modifier| { + Keybinding::new("C".to_string(), ModifierKeys::new().add(modifier)) + })), + ) + .child(Story::label(cx, "Single Key with Modifier (Permuted)")) + .child( + div().flex().flex_col().children( + all_modifier_permutations + .chunks(4) + .into_iter() + .map(|chunk| { + div() + .flex() + .gap_4() + .py_3() + .children(chunk.map(|permutation| { + let mut modifiers = ModifierKeys::new(); + + for modifier in permutation { + modifiers = modifiers.add(modifier); + } + + Keybinding::new("X".to_string(), modifiers) + })) + }), + ), + ) + .child(Story::label(cx, "Single Key with All Modifiers")) + .child(Keybinding::new("Z".to_string(), ModifierKeys::all())) + .child(Story::label(cx, "Chord")) + .child(Keybinding::new_chord( + ("A".to_string(), ModifierKeys::new()), + ("Z".to_string(), ModifierKeys::new()), + )) + .child(Story::label(cx, "Chord with Modifier")) + .child(Keybinding::new_chord( + ("A".to_string(), ModifierKeys::new().control(true)), + ("Z".to_string(), ModifierKeys::new().shift(true)), + )) + } + } +} diff --git a/crates/ui2/src/components/language_selector.rs b/crates/ui2/src/components/language_selector.rs index 9de9f4e8ab..41e33596b8 100644 --- a/crates/ui2/src/components/language_selector.rs +++ b/crates/ui2/src/components/language_selector.rs @@ -38,3 +38,33 @@ impl LanguageSelector { ) } } + +#[cfg(feature = "stories")] +pub use stories::*; + +#[cfg(feature = "stories")] +mod stories { + use crate::Story; + + use super::*; + + #[derive(Element)] + pub struct LanguageSelectorStory { + state_type: PhantomData, + } + + impl LanguageSelectorStory { + pub fn new() -> Self { + Self { + state_type: PhantomData, + } + } + + fn render(&mut self, cx: &mut ViewContext) -> impl Element { + Story::container(cx) + .child(Story::title_for::<_, LanguageSelector>(cx)) + .child(Story::label(cx, "Default")) + .child(LanguageSelector::new()) + } + } +} diff --git a/crates/ui2/src/components/multi_buffer.rs b/crates/ui2/src/components/multi_buffer.rs index 8c6fac0601..d5a3d8f539 100644 --- a/crates/ui2/src/components/multi_buffer.rs +++ b/crates/ui2/src/components/multi_buffer.rs @@ -40,3 +40,41 @@ impl MultiBuffer { })) } } + +#[cfg(feature = "stories")] +pub use stories::*; + +#[cfg(feature = "stories")] +mod stories { + use crate::{hello_world_rust_buffer_example, Story}; + + use super::*; + + #[derive(Element)] + pub struct MultiBufferStory { + state_type: PhantomData, + } + + impl MultiBufferStory { + pub fn new() -> Self { + Self { + state_type: PhantomData, + } + } + + fn render(&mut self, cx: &mut ViewContext) -> impl Element { + let theme = theme(cx); + + Story::container(cx) + .child(Story::title_for::<_, MultiBuffer>(cx)) + .child(Story::label(cx, "Default")) + .child(MultiBuffer::new(vec![ + hello_world_rust_buffer_example(&theme), + hello_world_rust_buffer_example(&theme), + hello_world_rust_buffer_example(&theme), + hello_world_rust_buffer_example(&theme), + hello_world_rust_buffer_example(&theme), + ])) + } + } +} diff --git a/crates/ui2/src/components/palette.rs b/crates/ui2/src/components/palette.rs index 76e6e16f71..0ee359db6a 100644 --- a/crates/ui2/src/components/palette.rs +++ b/crates/ui2/src/components/palette.rs @@ -150,3 +150,72 @@ impl PaletteItem { .children(self.keybinding.clone()) } } + +#[cfg(feature = "stories")] +pub use stories::*; + +#[cfg(feature = "stories")] +mod stories { + use crate::{ModifierKeys, Story}; + + use super::*; + + #[derive(Element)] + pub struct PaletteStory { + state_type: PhantomData, + } + + impl PaletteStory { + pub fn new() -> Self { + Self { + state_type: PhantomData, + } + } + + fn render(&mut self, cx: &mut ViewContext) -> impl Element { + Story::container(cx) + .child(Story::title_for::<_, Palette>(cx)) + .child(Story::label(cx, "Default")) + .child(Palette::new(ScrollState::default())) + .child(Story::label(cx, "With Items")) + .child( + Palette::new(ScrollState::default()) + .placeholder("Execute a command...") + .items(vec![ + PaletteItem::new("theme selector: toggle").keybinding( + Keybinding::new_chord( + ("k".to_string(), ModifierKeys::new().command(true)), + ("t".to_string(), ModifierKeys::new().command(true)), + ), + ), + PaletteItem::new("assistant: inline assist").keybinding( + Keybinding::new( + "enter".to_string(), + ModifierKeys::new().command(true), + ), + ), + PaletteItem::new("assistant: quote selection").keybinding( + Keybinding::new(">".to_string(), ModifierKeys::new().command(true)), + ), + PaletteItem::new("assistant: toggle focus").keybinding( + Keybinding::new("?".to_string(), ModifierKeys::new().command(true)), + ), + PaletteItem::new("auto update: check"), + PaletteItem::new("auto update: view release notes"), + PaletteItem::new("branches: open recent").keybinding(Keybinding::new( + "b".to_string(), + ModifierKeys::new().command(true).alt(true), + )), + PaletteItem::new("chat panel: toggle focus"), + PaletteItem::new("cli: install"), + PaletteItem::new("client: sign in"), + PaletteItem::new("client: sign out"), + PaletteItem::new("editor: cancel").keybinding(Keybinding::new( + "escape".to_string(), + ModifierKeys::new(), + )), + ]), + ) + } + } +} diff --git a/crates/ui2/src/components/panel.rs b/crates/ui2/src/components/panel.rs index 1a6b333a2c..f82dbad3e4 100644 --- a/crates/ui2/src/components/panel.rs +++ b/crates/ui2/src/components/panel.rs @@ -143,3 +143,42 @@ impl Panel { panel_base.children_any((self.children)(cx, self.payload.as_ref())) } } + +#[cfg(feature = "stories")] +pub use stories::*; + +#[cfg(feature = "stories")] +mod stories { + use crate::{Label, Story}; + + use super::*; + + #[derive(Element)] + pub struct PanelStory { + state_type: PhantomData, + } + + impl PanelStory { + pub fn new() -> Self { + Self { + state_type: PhantomData, + } + } + + fn render(&mut self, cx: &mut ViewContext) -> impl Element { + Story::container(cx) + .child(Story::title_for::<_, Panel>(cx)) + .child(Story::label(cx, "Default")) + .child(Panel::new( + ScrollState::default(), + |_, _| { + vec![div() + .overflow_y_scroll(ScrollState::default()) + .children((0..100).map(|ix| Label::new(format!("Item {}", ix + 1)))) + .into_any()] + }, + Box::new(()), + )) + } + } +} diff --git a/crates/ui2/src/components/project_panel.rs b/crates/ui2/src/components/project_panel.rs index 59a81ace81..cdc658ab3c 100644 --- a/crates/ui2/src/components/project_panel.rs +++ b/crates/ui2/src/components/project_panel.rs @@ -56,3 +56,37 @@ impl ProjectPanel { ) } } + +#[cfg(feature = "stories")] +pub use stories::*; + +#[cfg(feature = "stories")] +mod stories { + use crate::{Panel, Story}; + + use super::*; + + #[derive(Element)] + pub struct ProjectPanelStory { + state_type: PhantomData, + } + + impl ProjectPanelStory { + pub fn new() -> Self { + Self { + state_type: PhantomData, + } + } + + fn render(&mut self, cx: &mut ViewContext) -> impl Element { + Story::container(cx) + .child(Story::title_for::<_, ProjectPanel>(cx)) + .child(Story::label(cx, "Default")) + .child(Panel::new( + ScrollState::default(), + |_, _| vec![ProjectPanel::new(ScrollState::default()).into_any()], + Box::new(()), + )) + } + } +} diff --git a/crates/ui2/src/components/recent_projects.rs b/crates/ui2/src/components/recent_projects.rs index 2bdc4ea3ec..44f5bcbaf1 100644 --- a/crates/ui2/src/components/recent_projects.rs +++ b/crates/ui2/src/components/recent_projects.rs @@ -34,3 +34,33 @@ impl RecentProjects { ) } } + +#[cfg(feature = "stories")] +pub use stories::*; + +#[cfg(feature = "stories")] +mod stories { + use crate::Story; + + use super::*; + + #[derive(Element)] + pub struct RecentProjectsStory { + state_type: PhantomData, + } + + impl RecentProjectsStory { + pub fn new() -> Self { + Self { + state_type: PhantomData, + } + } + + fn render(&mut self, cx: &mut ViewContext) -> impl Element { + Story::container(cx) + .child(Story::title_for::<_, RecentProjects>(cx)) + .child(Story::label(cx, "Default")) + .child(RecentProjects::new()) + } + } +} diff --git a/crates/ui2/src/components/tab.rs b/crates/ui2/src/components/tab.rs index c53ac6f8f6..8ed34580c9 100644 --- a/crates/ui2/src/components/tab.rs +++ b/crates/ui2/src/components/tab.rs @@ -133,3 +133,109 @@ impl Tab { ) } } + +#[cfg(feature = "stories")] +pub use stories::*; + +#[cfg(feature = "stories")] +mod stories { + use strum::IntoEnumIterator; + + use crate::{h_stack, v_stack, Icon, Story}; + + use super::*; + + #[derive(Element)] + pub struct TabStory { + state_type: PhantomData, + } + + impl TabStory { + pub fn new() -> Self { + Self { + state_type: PhantomData, + } + } + + fn render(&mut self, cx: &mut ViewContext) -> impl Element { + let git_statuses = GitStatus::iter(); + let fs_statuses = FileSystemStatus::iter(); + + Story::container(cx) + .child(Story::title_for::<_, Tab>(cx)) + .child( + h_stack().child( + v_stack() + .gap_2() + .child(Story::label(cx, "Default")) + .child(Tab::new()), + ), + ) + .child( + h_stack().child( + v_stack().gap_2().child(Story::label(cx, "Current")).child( + h_stack() + .gap_4() + .child(Tab::new().title("Current".to_string()).current(true)) + .child(Tab::new().title("Not Current".to_string()).current(false)), + ), + ), + ) + .child( + h_stack().child( + v_stack() + .gap_2() + .child(Story::label(cx, "Titled")) + .child(Tab::new().title("label".to_string())), + ), + ) + .child( + h_stack().child( + v_stack() + .gap_2() + .child(Story::label(cx, "With Icon")) + .child( + Tab::new() + .title("label".to_string()) + .icon(Some(Icon::Envelope)), + ), + ), + ) + .child( + h_stack().child( + v_stack() + .gap_2() + .child(Story::label(cx, "Close Side")) + .child( + h_stack() + .gap_4() + .child( + Tab::new() + .title("Left".to_string()) + .close_side(IconSide::Left), + ) + .child(Tab::new().title("Right".to_string())), + ), + ), + ) + .child( + v_stack() + .gap_2() + .child(Story::label(cx, "Git Status")) + .child(h_stack().gap_4().children(git_statuses.map(|git_status| { + Tab::new() + .title(git_status.to_string()) + .git_status(git_status) + }))), + ) + .child( + v_stack() + .gap_2() + .child(Story::label(cx, "File System Status")) + .child(h_stack().gap_4().children(fs_statuses.map(|fs_status| { + Tab::new().title(fs_status.to_string()).fs_status(fs_status) + }))), + ) + } + } +} diff --git a/crates/ui2/src/components/tab_bar.rs b/crates/ui2/src/components/tab_bar.rs index b9393d830b..451dd858a0 100644 --- a/crates/ui2/src/components/tab_bar.rs +++ b/crates/ui2/src/components/tab_bar.rs @@ -83,3 +83,63 @@ impl TabBar { ) } } + +#[cfg(feature = "stories")] +pub use stories::*; + +#[cfg(feature = "stories")] +mod stories { + use crate::Story; + + use super::*; + + #[derive(Element)] + pub struct TabBarStory { + state_type: PhantomData, + } + + impl TabBarStory { + pub fn new() -> Self { + Self { + state_type: PhantomData, + } + } + + fn render(&mut self, cx: &mut ViewContext) -> impl Element { + Story::container(cx) + .child(Story::title_for::<_, TabBar>(cx)) + .child(Story::label(cx, "Default")) + .child(TabBar::new(vec![ + Tab::new() + .title("Cargo.toml".to_string()) + .current(false) + .git_status(GitStatus::Modified), + Tab::new() + .title("Channels Panel".to_string()) + .current(false), + Tab::new() + .title("channels_panel.rs".to_string()) + .current(true) + .git_status(GitStatus::Modified), + Tab::new() + .title("workspace.rs".to_string()) + .current(false) + .git_status(GitStatus::Modified), + Tab::new() + .title("icon_button.rs".to_string()) + .current(false), + Tab::new() + .title("storybook.rs".to_string()) + .current(false) + .git_status(GitStatus::Created), + Tab::new().title("theme.rs".to_string()).current(false), + Tab::new() + .title("theme_registry.rs".to_string()) + .current(false), + Tab::new() + .title("styleable_helpers.rs".to_string()) + .current(false), + ])) + } + } +} diff --git a/crates/ui2/src/components/terminal.rs b/crates/ui2/src/components/terminal.rs index 96be31a895..18fdc40f45 100644 --- a/crates/ui2/src/components/terminal.rs +++ b/crates/ui2/src/components/terminal.rs @@ -87,3 +87,33 @@ impl Terminal { )) } } + +#[cfg(feature = "stories")] +pub use stories::*; + +#[cfg(feature = "stories")] +mod stories { + use crate::Story; + + use super::*; + + #[derive(Element)] + pub struct TerminalStory { + state_type: PhantomData, + } + + impl TerminalStory { + pub fn new() -> Self { + Self { + state_type: PhantomData, + } + } + + fn render(&mut self, cx: &mut ViewContext) -> impl Element { + Story::container(cx) + .child(Story::title_for::<_, Terminal>(cx)) + .child(Story::label(cx, "Default")) + .child(Terminal::new()) + } + } +} diff --git a/crates/ui2/src/components/theme_selector.rs b/crates/ui2/src/components/theme_selector.rs index d51b5c7426..7bb49601df 100644 --- a/crates/ui2/src/components/theme_selector.rs +++ b/crates/ui2/src/components/theme_selector.rs @@ -39,3 +39,33 @@ impl ThemeSelector { ) } } + +#[cfg(feature = "stories")] +pub use stories::*; + +#[cfg(feature = "stories")] +mod stories { + use crate::Story; + + use super::*; + + #[derive(Element)] + pub struct ThemeSelectorStory { + state_type: PhantomData, + } + + impl ThemeSelectorStory { + pub fn new() -> Self { + Self { + state_type: PhantomData, + } + } + + fn render(&mut self, cx: &mut ViewContext) -> impl Element { + Story::container(cx) + .child(Story::title_for::<_, ThemeSelector>(cx)) + .child(Story::label(cx, "Default")) + .child(ThemeSelector::new()) + } + } +} diff --git a/crates/ui2/src/components/title_bar.rs b/crates/ui2/src/components/title_bar.rs index 79c0b53890..1ab9efdd61 100644 --- a/crates/ui2/src/components/title_bar.rs +++ b/crates/ui2/src/components/title_bar.rs @@ -117,3 +117,33 @@ impl TitleBar { ) } } + +#[cfg(feature = "stories")] +pub use stories::*; + +#[cfg(feature = "stories")] +mod stories { + use crate::Story; + + use super::*; + + #[derive(Element)] + pub struct TitleBarStory { + state_type: PhantomData, + } + + impl TitleBarStory { + pub fn new() -> Self { + Self { + state_type: PhantomData, + } + } + + fn render(&mut self, cx: &mut ViewContext) -> impl Element { + Story::container(cx) + .child(Story::title_for::<_, TitleBar>(cx)) + .child(Story::label(cx, "Default")) + .child(TitleBar::new(cx)) + } + } +} diff --git a/crates/ui2/src/components/toast.rs b/crates/ui2/src/components/toast.rs index 684e453bfb..be165b4646 100644 --- a/crates/ui2/src/components/toast.rs +++ b/crates/ui2/src/components/toast.rs @@ -65,3 +65,39 @@ impl Toast { .children_any((self.children)(cx, self.payload.as_ref())) } } + +#[cfg(feature = "stories")] +pub use stories::*; + +#[cfg(feature = "stories")] +mod stories { + use std::marker::PhantomData; + + use crate::{Label, Story}; + + use super::*; + + #[derive(Element)] + pub struct ToastStory { + state_type: PhantomData, + } + + impl ToastStory { + pub fn new() -> Self { + Self { + state_type: PhantomData, + } + } + + fn render(&mut self, cx: &mut ViewContext) -> impl Element { + Story::container(cx) + .child(Story::title_for::<_, Toast>(cx)) + .child(Story::label(cx, "Default")) + .child(Toast::new( + ToastOrigin::Bottom, + |_, _| vec![Label::new("label").into_any()], + Box::new(()), + )) + } + } +} diff --git a/crates/ui2/src/components/toolbar.rs b/crates/ui2/src/components/toolbar.rs index 27905589fb..0c1d998d28 100644 --- a/crates/ui2/src/components/toolbar.rs +++ b/crates/ui2/src/components/toolbar.rs @@ -47,3 +47,88 @@ impl Toolbar { ) } } + +#[cfg(feature = "stories")] +pub use stories::*; + +#[cfg(feature = "stories")] +mod stories { + use std::marker::PhantomData; + use std::path::PathBuf; + use std::str::FromStr; + use std::sync::Arc; + + use crate::{Breadcrumb, HighlightedText, Icon, IconButton, Story, Symbol}; + + use super::*; + + #[derive(Element)] + pub struct ToolbarStory { + state_type: PhantomData, + } + + impl ToolbarStory { + pub fn new() -> Self { + Self { + state_type: PhantomData, + } + } + + fn render(&mut self, cx: &mut ViewContext) -> impl Element { + let theme = theme(cx); + + struct LeftItemsPayload { + pub theme: Arc, + } + + Story::container(cx) + .child(Story::title_for::<_, Toolbar>(cx)) + .child(Story::label(cx, "Default")) + .child(Toolbar::new( + |_, payload| { + let payload = payload.downcast_ref::().unwrap(); + + let theme = payload.theme.clone(); + + vec![Breadcrumb::new( + PathBuf::from_str("crates/ui/src/components/toolbar.rs").unwrap(), + vec![ + Symbol(vec![ + HighlightedText { + text: "impl ".to_string(), + color: HighlightColor::Keyword.hsla(&theme), + }, + HighlightedText { + text: "ToolbarStory".to_string(), + color: HighlightColor::Function.hsla(&theme), + }, + ]), + Symbol(vec![ + HighlightedText { + text: "fn ".to_string(), + color: HighlightColor::Keyword.hsla(&theme), + }, + HighlightedText { + text: "render".to_string(), + color: HighlightColor::Function.hsla(&theme), + }, + ]), + ], + ) + .into_any()] + }, + Box::new(LeftItemsPayload { + theme: theme.clone(), + }), + |_, _| { + vec![ + IconButton::new(Icon::InlayHint).into_any(), + IconButton::new(Icon::MagnifyingGlass).into_any(), + IconButton::new(Icon::MagicWand).into_any(), + ] + }, + Box::new(()), + )) + } + } +} diff --git a/crates/ui2/src/components/traffic_lights.rs b/crates/ui2/src/components/traffic_lights.rs index 122171fdf5..fd7f67b904 100644 --- a/crates/ui2/src/components/traffic_lights.rs +++ b/crates/ui2/src/components/traffic_lights.rs @@ -82,3 +82,35 @@ impl TrafficLights { )) } } + +#[cfg(feature = "stories")] +pub use stories::*; + +#[cfg(feature = "stories")] +mod stories { + use crate::Story; + + use super::*; + + #[derive(Element)] + pub struct TrafficLightsStory { + state_type: PhantomData, + } + + impl TrafficLightsStory { + pub fn new() -> Self { + Self { + state_type: PhantomData, + } + } + + fn render(&mut self, cx: &mut ViewContext) -> impl Element { + Story::container(cx) + .child(Story::title_for::<_, TrafficLights>(cx)) + .child(Story::label(cx, "Default")) + .child(TrafficLights::new()) + .child(Story::label(cx, "Unfocused")) + .child(TrafficLights::new().window_has_focus(false)) + } + } +} diff --git a/crates/ui2/src/components/workspace.rs b/crates/ui2/src/components/workspace.rs index c40491d4b6..ec7c662ec2 100644 --- a/crates/ui2/src/components/workspace.rs +++ b/crates/ui2/src/components/workspace.rs @@ -195,3 +195,29 @@ impl WorkspaceElement { )) } } + +#[cfg(feature = "stories")] +pub use stories::*; + +#[cfg(feature = "stories")] +mod stories { + use super::*; + + #[derive(Element)] + pub struct WorkspaceStory { + state_type: PhantomData, + } + + impl WorkspaceStory { + pub fn new() -> Self { + Self { + state_type: PhantomData, + } + } + + fn render(&mut self, cx: &mut ViewContext) -> impl Element { + // Just render the workspace without any story boilerplate. + WorkspaceElement::new() + } + } +}