diff --git a/Cargo.lock b/Cargo.lock index 4b2f9146b4380aacd36c23672ae0170eb312e85c..f5452ac2e0e4e565d7949d26aca2e249e70d8441 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 95b8844157c8ab72383cb10ea7a7c6dbe38efc06..5df182e193d2058455f3c02f2f4fcf60b0a657d7 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 4c7db1bcdf7446d64888b55457b9edb220571ef5..0000000000000000000000000000000000000000 --- 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 48eed1f7ef4d053b4b6797a405514a028352e3b9..0000000000000000000000000000000000000000 --- 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 d253b887e82da633af83834a1bf475b06bac0c44..0000000000000000000000000000000000000000 --- 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 cdf3f862c3282190901640d8857d62cab8f9c6f3..0000000000000000000000000000000000000000 --- 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 d1a3b072d7e14d7d21ea96435b5e7a820a1e52fb..0000000000000000000000000000000000000000 --- 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 d3575cdb50e8832c8edaec8891173670fbcba8fb..0000000000000000000000000000000000000000 --- 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 f93f97f133263240c8d45844aa09c03e96369e12..0000000000000000000000000000000000000000 --- 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 54599e5e89566d9a307465b7e35cc0cc5a878bb4..0000000000000000000000000000000000000000 --- 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 434a587cfcfcc2927b30feb003884551d822ec1c..0000000000000000000000000000000000000000 --- 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 cd167658dc532b96f1d4df8e9694c987dc91c7c5..0000000000000000000000000000000000000000 --- 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 d4b0c7fdb585c9362d77f0309923a084a4ee7cfe..0000000000000000000000000000000000000000 --- 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 1cdbd995a676c4dd8dbffea5c01333d436a998fb..0000000000000000000000000000000000000000 --- 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 9470bda4bd9847189c250f87fc093c5ea7d18c0d..0000000000000000000000000000000000000000 --- 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 c2fb4edd4925ca8070d11be451556b010473b16d..0000000000000000000000000000000000000000 --- 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 d347092f79b4fd16c327adbf68b0b8bd15205fea..0000000000000000000000000000000000000000 --- 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 d2435d780b1dea31e4016525d70c8e1692b1a59a..0000000000000000000000000000000000000000 --- 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 d3461418b3edc21d53eccef32cee367ef0d73283..0000000000000000000000000000000000000000 --- 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 6a63306ed914de1b5ab525755776c1edfbae0875..0000000000000000000000000000000000000000 --- 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 b766a9afacd7038c61b6d979c074023a51b2c4d5..0000000000000000000000000000000000000000 --- 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 b0cf2cd7711de64e0bff5eae8dd747b91b44da8b..0000000000000000000000000000000000000000 --- 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 65cf4abde8bde35986011606db4aabc727f6fd62..0000000000000000000000000000000000000000 --- 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 451ce76aabe113665e320d29f3b551529428e4a1..0000000000000000000000000000000000000000 --- 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 056e258aaaba5145bfa90e51fe0d404f6dab8b07..0000000000000000000000000000000000000000 --- 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 e9d8b4ace2240e1d821f3d66c4abd388bdf94e8c..0000000000000000000000000000000000000000 --- 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 9ee9272eda8fbae9dcaf3e768191a6d93ff810a0..a2aeab3ced7d777b1db7c7b308d94a50c32249d3 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 248abcd38744b77d177467df7f5f67e8453f3b9a..3fe37da8fc25c4527c3f34802f95ac5c495fc314 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 8fa9922cc031a2ce46360dcc8826365f9e300f25..def22af18bb17db96462ab2a30237ce1d3848962 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 c0760ef8021051a68836b9c098bb2484d826ad98..8572859c31777e082f354204cc10ad160c7b3c11 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 d753202841d66cf1903f46690717883c902aa877..89ecad19dbf6e5ca6dda5f9d09a1f0542f7b332d 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 e0cdd3382de4d45abceab5b3b11737ba1d4fe077..ab4f5853cef680be627b7c575038d2188b0f9cb8 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 5a0098939aa690b94bbbb5a4bca7657f829af00f..991101fb135d3737e79be6182e19e76292a79d7b 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 61e20d853541118d649e0d1f1d333f8a46d1c5b8..6c29a787f55def2a3ee1f1eb859fe5bbf6f154a7 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 9fa7e7c6350246c06bb091042598ce5f611f8efa..ab02628816d6ecee0622b415bec309681e250b03 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 b7f1f78216e6a7b11d3be1df14373cb8e538b5e8..3a0aa055c2fb0d642b7741219282bc02830751e4 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 e516ad177f3d77d7e0417d349eb7877675860dc0..3830d1a3e5fbe6fb0cfcf88d4b2d1be3f0e81bac 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 9de9f4e8ab2bf99b120b4d49c5a767dd1857dbfe..41e33596b86e005b9c69e78224473373357170b9 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 8c6fac0601689dcb49f29a4de277802d2eb457d7..d5a3d8f53979f23ae6ac8b0d21334749b12284a1 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 76e6e16f716c58a6ac0b0a8e67a0ed1961d3aac2..0ee359db6a37f36958afe116020c262320211115 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 1a6b333a2caa8200eb29aae9ecbf598d3b5720a6..f82dbad3e4b7508fd9341900199333432a17b58f 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 59a81ace81369f91fb0f7b923e1ca3c90e365289..cdc658ab3c07d0493b14f65834f53f705e423809 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 2bdc4ea3ec2566a2424a1edb94756002fa184757..44f5bcbaf10f273601bd176ccf95d46fb9ce863d 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 c53ac6f8f626458ae4dc694623d320c06d31a7ec..8ed34580c9ab2d9a75a78ca0c023dbe41af8e938 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 b9393d830bfb22f31b9611bff1f7f6a5df9a0587..451dd858a0f26cbb68f56d75e01b6c5a6333cf42 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 96be31a895dd28312357862c901bdd0adf0d040f..18fdc40f457b9c5c91b5fdffb5fbd8ec9d06149a 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 d51b5c74264a9f03d5327b18d46fe6c7730e8bc1..7bb49601dff0939dd1bcb78c00ee57f16cdce75c 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 79c0b538905da4010f0a84a6e590bbf4fe36aae6..1ab9efdd61ea55d479cae5cfcbcb77b916b205c5 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 684e453bfb405b3b58dbf1fade51ab0efc5ee691..be165b4646ceb6994fc466490402ba4784b95f91 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 27905589fb4ed4edf780238828d40872cdc8e59b..0c1d998d2869bf722f328afc0080e4ca01902826 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 122171fdf53f9ace5975fd7ce81149277b7951ff..fd7f67b904a6f5cd86eee7d645908a4555b33290 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 c40491d4b61ad4f79b857d8e7559d75dee7513da..ec7c662ec2d9f25ae78d1df9d68dbf01edaecfed 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() + } + } +}