From 1b05aad30ca4c8d5b2fc157e4f50cabc70dcc996 Mon Sep 17 00:00:00 2001 From: Marshall Bowers Date: Tue, 21 Nov 2023 13:42:00 -0500 Subject: [PATCH] Extract `Story` into separate `story` crate (#3378) This PR extracts the `Story` component into a separate `story` crate so that it can be shared among various crates that define stories. Release Notes: - N/A --------- Co-authored-by: Nate Butler --- Cargo.lock | 9 ++ Cargo.toml | 1 + crates/story/Cargo.toml | 10 ++ crates/story/src/lib.rs | 3 + crates/story/src/story.rs | 35 +++++ crates/storybook2/Cargo.toml | 1 + crates/storybook2/src/stories/colors.rs | 44 ------ crates/theme2/Cargo.toml | 5 +- crates/theme2/src/story.rs | 38 ----- crates/theme2/src/styles.rs | 6 + crates/theme2/src/styles/players.rs | 140 +----------------- crates/theme2/src/styles/stories/color.rs | 41 +++++ crates/theme2/src/styles/stories/mod.rs | 5 + crates/theme2/src/styles/stories/players.rs | 137 +++++++++++++++++ crates/theme2/src/theme2.rs | 5 - crates/ui2/Cargo.toml | 3 +- crates/ui2/src/components/stories/avatar.rs | 9 +- crates/ui2/src/components/stories/button.rs | 27 ++-- crates/ui2/src/components/stories/checkbox.rs | 11 +- .../src/components/stories/context_menu.rs | 5 +- crates/ui2/src/components/stories/icon.rs | 9 +- crates/ui2/src/components/stories/input.rs | 9 +- .../ui2/src/components/stories/keybinding.rs | 19 +-- crates/ui2/src/components/stories/label.rs | 11 +- crates/ui2/src/story.rs | 37 ----- crates/ui2/src/ui2.rs | 5 - 26 files changed, 309 insertions(+), 316 deletions(-) create mode 100644 crates/story/Cargo.toml create mode 100644 crates/story/src/lib.rs create mode 100644 crates/story/src/story.rs delete mode 100644 crates/storybook2/src/stories/colors.rs delete mode 100644 crates/theme2/src/story.rs create mode 100644 crates/theme2/src/styles/stories/color.rs create mode 100644 crates/theme2/src/styles/stories/mod.rs create mode 100644 crates/theme2/src/styles/stories/players.rs delete mode 100644 crates/ui2/src/story.rs diff --git a/Cargo.lock b/Cargo.lock index 6aa94b08d0..d502ff4262 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -8859,6 +8859,13 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" +[[package]] +name = "story" +version = "0.1.0" +dependencies = [ + "gpui2", +] + [[package]] name = "stringprep" version = "0.1.4" @@ -9362,6 +9369,7 @@ dependencies = [ "serde_derive", "serde_json", "settings2", + "story", "toml 0.5.11", "util", "uuid 1.4.1", @@ -10205,6 +10213,7 @@ dependencies = [ "serde", "settings2", "smallvec", + "story", "strum", "theme2", ] diff --git a/Cargo.toml b/Cargo.toml index d7b9918f62..01a6a1e0c9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -111,6 +111,7 @@ members = [ "crates/ui2", "crates/util", "crates/semantic_index", + "crates/story", "crates/vim", "crates/vcs_menu", "crates/workspace2", diff --git a/crates/story/Cargo.toml b/crates/story/Cargo.toml new file mode 100644 index 0000000000..384447af8f --- /dev/null +++ b/crates/story/Cargo.toml @@ -0,0 +1,10 @@ +[package] +name = "story" +version = "0.1.0" +edition = "2021" +publish = false + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +gpui = { package = "gpui2", path = "../gpui2" } diff --git a/crates/story/src/lib.rs b/crates/story/src/lib.rs new file mode 100644 index 0000000000..a9998e65a8 --- /dev/null +++ b/crates/story/src/lib.rs @@ -0,0 +1,3 @@ +mod story; + +pub use story::*; diff --git a/crates/story/src/story.rs b/crates/story/src/story.rs new file mode 100644 index 0000000000..d95c879ce0 --- /dev/null +++ b/crates/story/src/story.rs @@ -0,0 +1,35 @@ +use gpui::prelude::*; +use gpui::{div, hsla, Div, SharedString}; + +pub struct Story {} + +impl Story { + pub fn container() -> Div { + div().size_full().flex().flex_col().pt_2().px_4().bg(hsla( + 0. / 360., + 0. / 100., + 100. / 100., + 1., + )) + } + + pub fn title(title: impl Into) -> impl Element { + div() + .text_xl() + .text_color(hsla(0. / 360., 0. / 100., 0. / 100., 1.)) + .child(title.into()) + } + + pub fn title_for() -> impl Element { + Self::title(std::any::type_name::()) + } + + pub fn label(label: impl Into) -> impl Element { + div() + .mt_4() + .mb_2() + .text_xs() + .text_color(hsla(0. / 360., 0. / 100., 0. / 100., 1.)) + .child(label.into()) + } +} diff --git a/crates/storybook2/Cargo.toml b/crates/storybook2/Cargo.toml index 7c6776c930..16386706cf 100644 --- a/crates/storybook2/Cargo.toml +++ b/crates/storybook2/Cargo.toml @@ -25,6 +25,7 @@ serde.workspace = true settings2 = { path = "../settings2" } simplelog = "0.9" smallvec.workspace = true +story = { path = "../story" } strum = { version = "0.25.0", features = ["derive"] } theme = { path = "../theme" } theme2 = { path = "../theme2" } diff --git a/crates/storybook2/src/stories/colors.rs b/crates/storybook2/src/stories/colors.rs deleted file mode 100644 index 8a628a01da..0000000000 --- a/crates/storybook2/src/stories/colors.rs +++ /dev/null @@ -1,44 +0,0 @@ -use crate::story::Story; -use gpui::{prelude::*, px, Div, Render}; -use theme2::{default_color_scales, ColorScaleStep}; -use ui::prelude::*; - -pub struct ColorsStory; - -impl Render for ColorsStory { - type Element = Div; - - fn render(&mut self, cx: &mut ViewContext) -> Self::Element { - let color_scales = default_color_scales(); - - Story::container(cx) - .child(Story::title(cx, "Colors")) - .child( - div() - .id("colors") - .flex() - .flex_col() - .gap_1() - .overflow_y_scroll() - .text_color(gpui::white()) - .children(color_scales.into_iter().map(|scale| { - div() - .flex() - .child( - div() - .w(px(75.)) - .line_height(px(24.)) - .child(scale.name().clone()), - ) - .child( - div() - .flex() - .gap_1() - .children(ColorScaleStep::ALL.map(|step| { - div().flex().size_6().bg(scale.step(cx, step)) - })), - ) - })), - ) - } -} diff --git a/crates/theme2/Cargo.toml b/crates/theme2/Cargo.toml index 22bea20e16..9ed387ebce 100644 --- a/crates/theme2/Cargo.toml +++ b/crates/theme2/Cargo.toml @@ -5,9 +5,9 @@ edition = "2021" publish = false [features] -default = ["stories"] +default = [] importing-themes = [] -stories = ["dep:itertools"] +stories = ["dep:itertools", "dep:story"] test-support = [ "gpui/test-support", "fs/test-support", @@ -30,6 +30,7 @@ serde.workspace = true serde_derive.workspace = true serde_json.workspace = true settings = { package = "settings2", path = "../settings2" } +story = { path = "../story", optional = true } toml.workspace = true uuid.workspace = true util = { path = "../util" } diff --git a/crates/theme2/src/story.rs b/crates/theme2/src/story.rs deleted file mode 100644 index 5e484e12cd..0000000000 --- a/crates/theme2/src/story.rs +++ /dev/null @@ -1,38 +0,0 @@ -use gpui::{div, Div, Element, ParentElement, SharedString, Styled, WindowContext}; - -use crate::ActiveTheme; - -pub struct Story {} - -impl Story { - pub fn container(cx: &mut WindowContext) -> Div { - div() - .size_full() - .flex() - .flex_col() - .pt_2() - .px_4() - .font("Zed Mono") - .bg(cx.theme().colors().background) - } - - pub fn title(cx: &mut WindowContext, title: SharedString) -> impl Element { - div() - .text_xl() - .text_color(cx.theme().colors().text) - .child(title) - } - - pub fn title_for(cx: &mut WindowContext) -> impl Element { - Self::title(cx, std::any::type_name::().into()) - } - - pub fn label(cx: &mut WindowContext, label: impl Into) -> impl Element { - div() - .mt_4() - .mb_2() - .text_xs() - .text_color(cx.theme().colors().text) - .child(label.into()) - } -} diff --git a/crates/theme2/src/styles.rs b/crates/theme2/src/styles.rs index 18f9e76581..13a59f486d 100644 --- a/crates/theme2/src/styles.rs +++ b/crates/theme2/src/styles.rs @@ -4,8 +4,14 @@ mod status; mod syntax; mod system; +#[cfg(feature = "stories")] +mod stories; + pub use colors::*; pub use players::*; pub use status::*; pub use syntax::*; pub use system::*; + +#[cfg(feature = "stories")] +pub use stories::*; diff --git a/crates/theme2/src/styles/players.rs b/crates/theme2/src/styles/players.rs index a4734d1c00..e8bce8e578 100644 --- a/crates/theme2/src/styles/players.rs +++ b/crates/theme2/src/styles/players.rs @@ -1,5 +1,7 @@ use gpui::Hsla; +use crate::{amber, blue, jade, lime, orange, pink, purple, red}; + #[derive(Debug, Clone, Copy, Default)] pub struct PlayerColor { pub cursor: Hsla, @@ -133,141 +135,3 @@ impl PlayerColors { self.0[(participant_index as usize % len) + 1] } } - -#[cfg(feature = "stories")] -pub use stories::*; - -use crate::{amber, blue, jade, lime, orange, pink, purple, red}; - -#[cfg(feature = "stories")] -mod stories { - use super::*; - use crate::{ActiveTheme, Story}; - use gpui::{div, img, px, Div, ParentElement, Render, Styled, ViewContext}; - - pub struct PlayerStory; - - impl Render for PlayerStory { - type Element = Div; - - fn render(&mut self, cx: &mut ViewContext) -> Self::Element { - Story::container(cx).child( - div() - .flex() - .flex_col() - .gap_4() - .child(Story::title_for::(cx)) - .child(Story::label(cx, "Player Colors")) - .child( - div() - .flex() - .flex_col() - .gap_1() - .child( - div().flex().gap_1().children( - cx.theme().players().0.clone().iter_mut().map(|player| { - div().w_8().h_8().rounded_md().bg(player.cursor) - }), - ), - ) - .child(div().flex().gap_1().children( - cx.theme().players().0.clone().iter_mut().map(|player| { - div().w_8().h_8().rounded_md().bg(player.background) - }), - )) - .child(div().flex().gap_1().children( - cx.theme().players().0.clone().iter_mut().map(|player| { - div().w_8().h_8().rounded_md().bg(player.selection) - }), - )), - ) - .child(Story::label(cx, "Avatar Rings")) - .child(div().flex().gap_1().children( - cx.theme().players().0.clone().iter_mut().map(|player| { - div() - .my_1() - .rounded_full() - .border_2() - .border_color(player.cursor) - .child( - img() - .rounded_full() - .uri("https://avatars.githubusercontent.com/u/1714999?v=4") - .size_6() - .bg(gpui::red()), - ) - }), - )) - .child(Story::label(cx, "Player Backgrounds")) - .child(div().flex().gap_1().children( - cx.theme().players().0.clone().iter_mut().map(|player| { - div() - .my_1() - .rounded_xl() - .flex() - .items_center() - .h_8() - .py_0p5() - .px_1p5() - .bg(player.background) - .child( - div().relative().neg_mx_1().rounded_full().z_index(3) - .border_2() - .border_color(player.background) - .size(px(28.)) - .child( - img() - .rounded_full() - .uri("https://avatars.githubusercontent.com/u/1714999?v=4") - .size(px(24.)) - .bg(gpui::red()), - ), - ).child( - div().relative().neg_mx_1().rounded_full().z_index(2) - .border_2() - .border_color(player.background) - .size(px(28.)) - .child( - img() - .rounded_full() - .uri("https://avatars.githubusercontent.com/u/1714999?v=4") - .size(px(24.)) - .bg(gpui::red()), - ), - ).child( - div().relative().neg_mx_1().rounded_full().z_index(1) - .border_2() - .border_color(player.background) - .size(px(28.)) - .child( - img() - .rounded_full() - .uri("https://avatars.githubusercontent.com/u/1714999?v=4") - .size(px(24.)) - .bg(gpui::red()), - ), - ) - }), - )) - .child(Story::label(cx, "Player Selections")) - .child(div().flex().flex_col().gap_px().children( - cx.theme().players().0.clone().iter_mut().map(|player| { - div() - .flex() - .child( - div() - .flex() - .flex_none() - .rounded_sm() - .px_0p5() - .text_color(cx.theme().colors().text) - .bg(player.selection) - .child("The brown fox jumped over the lazy dog."), - ) - .child(div().flex_1()) - }), - )), - ) - } - } -} diff --git a/crates/theme2/src/styles/stories/color.rs b/crates/theme2/src/styles/stories/color.rs new file mode 100644 index 0000000000..a7d8885848 --- /dev/null +++ b/crates/theme2/src/styles/stories/color.rs @@ -0,0 +1,41 @@ +use gpui::prelude::*; +use gpui::{div, px, Div, ViewContext}; +use story::Story; + +use crate::{default_color_scales, ColorScaleStep}; + +pub struct ColorsStory; + +impl Render for ColorsStory { + type Element = Div; + + fn render(&mut self, cx: &mut ViewContext) -> Self::Element { + let color_scales = default_color_scales(); + + Story::container().child(Story::title("Colors")).child( + div() + .id("colors") + .flex() + .flex_col() + .gap_1() + .overflow_y_scroll() + .text_color(gpui::white()) + .children(color_scales.into_iter().map(|scale| { + div() + .flex() + .child( + div() + .w(px(75.)) + .line_height(px(24.)) + .child(scale.name().clone()), + ) + .child( + div().flex().gap_1().children( + ColorScaleStep::ALL + .map(|step| div().flex().size_6().bg(scale.step(cx, step))), + ), + ) + })), + ) + } +} diff --git a/crates/theme2/src/styles/stories/mod.rs b/crates/theme2/src/styles/stories/mod.rs new file mode 100644 index 0000000000..af6af96548 --- /dev/null +++ b/crates/theme2/src/styles/stories/mod.rs @@ -0,0 +1,5 @@ +mod color; +mod players; + +pub use color::*; +pub use players::*; diff --git a/crates/theme2/src/styles/stories/players.rs b/crates/theme2/src/styles/stories/players.rs new file mode 100644 index 0000000000..d189d3bfb0 --- /dev/null +++ b/crates/theme2/src/styles/stories/players.rs @@ -0,0 +1,137 @@ +use gpui::{div, img, px, Div, ParentElement, Render, Styled, ViewContext}; +use story::Story; + +use crate::{ActiveTheme, PlayerColors}; + +pub struct PlayerStory; + +impl Render for PlayerStory { + type Element = Div; + + fn render(&mut self, cx: &mut ViewContext) -> Self::Element { + Story::container().child( + div() + .flex() + .flex_col() + .gap_4() + .child(Story::title_for::()) + .child(Story::label("Player Colors")) + .child( + div() + .flex() + .flex_col() + .gap_1() + .child( + div().flex().gap_1().children( + cx.theme() + .players() + .0 + .clone() + .iter_mut() + .map(|player| div().w_8().h_8().rounded_md().bg(player.cursor)), + ), + ) + .child( + div().flex().gap_1().children( + cx.theme().players().0.clone().iter_mut().map(|player| { + div().w_8().h_8().rounded_md().bg(player.background) + }), + ), + ) + .child( + div().flex().gap_1().children( + cx.theme().players().0.clone().iter_mut().map(|player| { + div().w_8().h_8().rounded_md().bg(player.selection) + }), + ), + ), + ) + .child(Story::label("Avatar Rings")) + .child(div().flex().gap_1().children( + cx.theme().players().0.clone().iter_mut().map(|player| { + div() + .my_1() + .rounded_full() + .border_2() + .border_color(player.cursor) + .child( + img() + .rounded_full() + .uri("https://avatars.githubusercontent.com/u/1714999?v=4") + .size_6() + .bg(gpui::red()), + ) + }), + )) + .child(Story::label("Player Backgrounds")) + .child(div().flex().gap_1().children( + cx.theme().players().0.clone().iter_mut().map(|player| { + div() + .my_1() + .rounded_xl() + .flex() + .items_center() + .h_8() + .py_0p5() + .px_1p5() + .bg(player.background) + .child( + div().relative().neg_mx_1().rounded_full().z_index(3) + .border_2() + .border_color(player.background) + .size(px(28.)) + .child( + img() + .rounded_full() + .uri("https://avatars.githubusercontent.com/u/1714999?v=4") + .size(px(24.)) + .bg(gpui::red()), + ), + ).child( + div().relative().neg_mx_1().rounded_full().z_index(2) + .border_2() + .border_color(player.background) + .size(px(28.)) + .child( + img() + .rounded_full() + .uri("https://avatars.githubusercontent.com/u/1714999?v=4") + .size(px(24.)) + .bg(gpui::red()), + ), + ).child( + div().relative().neg_mx_1().rounded_full().z_index(1) + .border_2() + .border_color(player.background) + .size(px(28.)) + .child( + img() + .rounded_full() + .uri("https://avatars.githubusercontent.com/u/1714999?v=4") + .size(px(24.)) + .bg(gpui::red()), + ), + ) + }), + )) + .child(Story::label("Player Selections")) + .child(div().flex().flex_col().gap_px().children( + cx.theme().players().0.clone().iter_mut().map(|player| { + div() + .flex() + .child( + div() + .flex() + .flex_none() + .rounded_sm() + .px_0p5() + .text_color(cx.theme().colors().text) + .bg(player.selection) + .child("The brown fox jumped over the lazy dog."), + ) + .child(div().flex_1()) + }), + )), + ) + } +} diff --git a/crates/theme2/src/theme2.rs b/crates/theme2/src/theme2.rs index 39c5924fb9..03407beab9 100644 --- a/crates/theme2/src/theme2.rs +++ b/crates/theme2/src/theme2.rs @@ -144,8 +144,3 @@ pub struct DiagnosticStyle { pub hint: Hsla, pub ignored: Hsla, } - -#[cfg(feature = "stories")] -mod story; -#[cfg(feature = "stories")] -pub use story::*; diff --git a/crates/ui2/Cargo.toml b/crates/ui2/Cargo.toml index 0fa277dc89..9f98b92296 100644 --- a/crates/ui2/Cargo.toml +++ b/crates/ui2/Cargo.toml @@ -17,10 +17,11 @@ menu = { package = "menu2", path = "../menu2"} serde.workspace = true settings2 = { path = "../settings2" } smallvec.workspace = true +story = { path = "../story", optional = true } strum = { version = "0.25.0", features = ["derive"] } theme2 = { path = "../theme2" } rand = "0.8" [features] default = [] -stories = ["dep:itertools"] +stories = ["dep:itertools", "dep:story"] diff --git a/crates/ui2/src/components/stories/avatar.rs b/crates/ui2/src/components/stories/avatar.rs index 63276fd3e9..ad9c3ccb39 100644 --- a/crates/ui2/src/components/stories/avatar.rs +++ b/crates/ui2/src/components/stories/avatar.rs @@ -1,7 +1,8 @@ use gpui::{Div, Render}; +use story::Story; use crate::prelude::*; -use crate::{Avatar, Story}; +use crate::Avatar; pub struct AvatarStory; @@ -9,9 +10,9 @@ impl Render for AvatarStory { type Element = Div; fn render(&mut self, cx: &mut ViewContext) -> Self::Element { - Story::container(cx) - .child(Story::title_for::(cx)) - .child(Story::label(cx, "Default")) + Story::container() + .child(Story::title_for::()) + .child(Story::label("Default")) .child(Avatar::new( "https://avatars.githubusercontent.com/u/1714999?v=4", )) diff --git a/crates/ui2/src/components/stories/button.rs b/crates/ui2/src/components/stories/button.rs index 41483e3534..6a23060c78 100644 --- a/crates/ui2/src/components/stories/button.rs +++ b/crates/ui2/src/components/stories/button.rs @@ -1,8 +1,9 @@ use gpui::{rems, Div, Render}; +use story::Story; use strum::IntoEnumIterator; use crate::prelude::*; -use crate::{h_stack, v_stack, Button, Icon, IconPosition, Label, Story}; +use crate::{h_stack, v_stack, Button, Icon, IconPosition, Label}; pub struct ButtonStory; @@ -12,15 +13,15 @@ impl Render for ButtonStory { fn render(&mut self, cx: &mut ViewContext) -> Self::Element { let states = InteractionState::iter(); - Story::container(cx) - .child(Story::title_for::