diff --git a/crates/gpui2_macros/src/styleable_helpers.rs b/crates/gpui2_macros/src/styleable_helpers.rs index ae7b2d3b1b..d5d76ff33b 100644 --- a/crates/gpui2_macros/src/styleable_helpers.rs +++ b/crates/gpui2_macros/src/styleable_helpers.rs @@ -28,24 +28,24 @@ fn generate_methods() -> Vec { let mut methods = Vec::new(); for (prefix, auto_allowed, fields) in box_prefixes() { - for (suffix, length_tokens) in box_suffixes() { + for (suffix, length_tokens, doc_string) in box_suffixes() { if auto_allowed || suffix != "auto" { - let method = generate_method(prefix, suffix, &fields, length_tokens); + let method = generate_method(prefix, suffix, &fields, length_tokens, doc_string); methods.push(method); } } } for (prefix, fields) in corner_prefixes() { - for (suffix, radius_tokens) in corner_suffixes() { - let method = generate_method(prefix, suffix, &fields, radius_tokens); + for (suffix, radius_tokens, doc_string) in corner_suffixes() { + let method = generate_method(prefix, suffix, &fields, radius_tokens, doc_string); methods.push(method); } } for (prefix, fields) in border_prefixes() { - for (suffix, width_tokens) in border_suffixes() { - let method = generate_method(prefix, suffix, &fields, width_tokens); + for (suffix, width_tokens, doc_string) in border_suffixes() { + let method = generate_method(prefix, suffix, &fields, width_tokens, doc_string); methods.push(method); } } @@ -58,6 +58,7 @@ fn generate_method( suffix: &'static str, fields: &Vec, length_tokens: TokenStream2, + doc_string: &'static str, ) -> TokenStream2 { let method_name = if suffix.is_empty() { format_ident!("{}", prefix) @@ -75,6 +76,7 @@ fn generate_method( .collect::>(); let method = quote! { + #[doc = #doc_string] fn #method_name(mut self) -> Self where Self: std::marker::Sized { let mut style = self.declared_style(); #(#field_assignments)* @@ -160,55 +162,52 @@ fn box_prefixes() -> Vec<(&'static str, bool, Vec)> { ] } -fn box_suffixes() -> Vec<(&'static str, TokenStream2)> { +fn box_suffixes() -> Vec<(&'static str, TokenStream2, &'static str)> { vec![ - ("0", quote! { pixels(0.) }), - ("0p5", quote! { rems(0.125) }), - ("1", quote! { rems(0.25) }), - ("1p5", quote! { rems(0.375) }), - ("2", quote! { rems(0.5) }), - ("2p5", quote! { rems(0.625) }), - ("3", quote! { rems(0.75) }), - ("3p5", quote! { rems(0.875) }), - ("4", quote! { rems(1.) }), - ("5", quote! { rems(1.25) }), - ("6", quote! { rems(1.5) }), - ("7", quote! { rems(1.75) }), - ("8", quote! { rems(2.0) }), - ("9", quote! { rems(2.25) }), - ("10", quote! { rems(2.5) }), - ("11", quote! { rems(2.75) }), - ("12", quote! { rems(3.) }), - ("16", quote! { rems(4.) }), - ("20", quote! { rems(5.) }), - ("24", quote! { rems(6.) }), - ("32", quote! { rems(8.) }), - ("40", quote! { rems(10.) }), - ("48", quote! { rems(12.) }), - ("56", quote! { rems(14.) }), - ("64", quote! { rems(16.) }), - ("72", quote! { rems(18.) }), - ("80", quote! { rems(20.) }), - ("96", quote! { rems(24.) }), - ("auto", quote! { auto() }), - ("px", quote! { pixels(1.) }), - ("full", quote! { relative(1.) }), - ("1_2", quote! { relative(0.5) }), - ("1_3", quote! { relative(1./3.) }), - ("2_3", quote! { relative(2./3.) }), - ("1_4", quote! { relative(0.25) }), - ("2_4", quote! { relative(0.5) }), - ("3_4", quote! { relative(0.75) }), - ("1_5", quote! { relative(0.2) }), - ("2_5", quote! { relative(0.4) }), - ("3_5", quote! { relative(0.6) }), - ("4_5", quote! { relative(0.8) }), - ("1_6", quote! { relative(1./6.) }), - ("5_6", quote! { relative(5./6.) }), - ("1_12", quote! { relative(1./12.) }), - // ("screen_50", quote! { DefiniteLength::Vh(50.0) }), - // ("screen_75", quote! { DefiniteLength::Vh(75.0) }), - // ("screen", quote! { DefiniteLength::Vh(100.0) }), + ("0", quote! { pixels(0.) }, "0px"), + ("0p5", quote! { rems(0.125) }, "2px (0.125rem)"), + ("1", quote! { rems(0.25) }, "4px (0.25rem)"), + ("1p5", quote! { rems(0.375) }, "6px (0.375rem)"), + ("2", quote! { rems(0.5) }, "8px (0.5rem)"), + ("2p5", quote! { rems(0.625) }, "10px (0.625rem)"), + ("3", quote! { rems(0.75) }, "12px (0.75rem)"), + ("3p5", quote! { rems(0.875) }, "14px (0.875rem)"), + ("4", quote! { rems(1.) }, "16px (1rem)"), + ("5", quote! { rems(1.25) }, "20px (1.25rem)"), + ("6", quote! { rems(1.5) }, "24px (1.5rem)"), + ("7", quote! { rems(1.75) }, "28px (1.75rem)"), + ("8", quote! { rems(2.0) }, "32px (2rem)"), + ("9", quote! { rems(2.25) }, "36px (2.25rem)"), + ("10", quote! { rems(2.5) }, "40px (2.5rem)"), + ("11", quote! { rems(2.75) }, "44px (2.75rem)"), + ("12", quote! { rems(3.) }, "48px (3rem)"), + ("16", quote! { rems(4.) }, "64px (4rem)"), + ("20", quote! { rems(5.) }, "80px (5rem)"), + ("24", quote! { rems(6.) }, "96px (6rem)"), + ("32", quote! { rems(8.) }, "128px (8rem)"), + ("40", quote! { rems(10.) }, "160px (10rem)"), + ("48", quote! { rems(12.) }, "192px (12rem)"), + ("56", quote! { rems(14.) }, "224px (14rem)"), + ("64", quote! { rems(16.) }, "256px (16rem)"), + ("72", quote! { rems(18.) }, "288px (18rem)"), + ("80", quote! { rems(20.) }, "320px (20rem)"), + ("96", quote! { rems(24.) }, "384px (24rem)"), + ("auto", quote! { auto() }, "Auto"), + ("px", quote! { pixels(1.) }, "1px"), + ("full", quote! { relative(1.) }, "100%"), + ("1_2", quote! { relative(0.5) }, "50% (1/2)"), + ("1_3", quote! { relative(1./3.) }, "33% (1/3)"), + ("2_3", quote! { relative(2./3.) }, "66% (2/3)"), + ("1_4", quote! { relative(0.25) }, "25% (1/4)"), + ("2_4", quote! { relative(0.5) }, "50% (2/4)"), + ("3_4", quote! { relative(0.75) }, "75% (3/4)"), + ("1_5", quote! { relative(0.2) }, "20% (1/5)"), + ("2_5", quote! { relative(0.4) }, "40% (2/5)"), + ("3_5", quote! { relative(0.6) }, "60% (3/5)"), + ("4_5", quote! { relative(0.8) }, "80% (4/5)"), + ("1_6", quote! { relative(1./6.) }, "16% (1/6)"), + ("5_6", quote! { relative(5./6.) }, "80% (5/6)"), + ("1_12", quote! { relative(1./12.) }, "8% (1/12)"), ] } @@ -258,16 +257,16 @@ fn corner_prefixes() -> Vec<(&'static str, Vec)> { ] } -fn corner_suffixes() -> Vec<(&'static str, TokenStream2)> { +fn corner_suffixes() -> Vec<(&'static str, TokenStream2, &'static str)> { vec![ - ("none", quote! { pixels(0.) }), - ("sm", quote! { rems(0.125) }), - ("md", quote! { rems(0.25) }), - ("lg", quote! { rems(0.5) }), - ("xl", quote! { rems(0.75) }), - ("2xl", quote! { rems(1.) }), - ("3xl", quote! { rems(1.5) }), - ("full", quote! { pixels(9999.) }), + ("none", quote! { pixels(0.) }, "0px"), + ("sm", quote! { rems(0.125) }, "2px (0.125rem)"), + ("md", quote! { rems(0.25) }, "4px (0.25rem)"), + ("lg", quote! { rems(0.5) }, "8px (0.5rem)"), + ("xl", quote! { rems(0.75) }, "12px (0.75rem)"), + ("2xl", quote! { rems(1.) }, "16px (1rem)"), + ("3xl", quote! { rems(1.5) }, "24px (1.5rem)"), + ("full", quote! { pixels(9999.) }, "9999px"), ] } @@ -303,25 +302,25 @@ fn border_prefixes() -> Vec<(&'static str, Vec)> { ] } -fn border_suffixes() -> Vec<(&'static str, TokenStream2)> { +fn border_suffixes() -> Vec<(&'static str, TokenStream2, &'static str)> { vec![ - ("", quote! { pixels(1.) }), - ("0", quote! { pixels(0.) }), - ("1", quote! { pixels(1.) }), - ("2", quote! { pixels(2.) }), - ("3", quote! { pixels(3.) }), - ("4", quote! { pixels(4.) }), - ("5", quote! { pixels(5.) }), - ("6", quote! { pixels(6.) }), - ("7", quote! { pixels(7.) }), - ("8", quote! { pixels(8.) }), - ("9", quote! { pixels(9.) }), - ("10", quote! { pixels(10.) }), - ("11", quote! { pixels(11.) }), - ("12", quote! { pixels(12.) }), - ("16", quote! { pixels(16.) }), - ("20", quote! { pixels(20.) }), - ("24", quote! { pixels(24.) }), - ("32", quote! { pixels(32.) }), + ("", quote! { pixels(1.)}, "1px"), + ("0", quote! { pixels(0.)}, "0px"), + ("1", quote! { pixels(1.) }, "1px"), + ("2", quote! { pixels(2.) }, "2px"), + ("3", quote! { pixels(3.) }, "3px"), + ("4", quote! { pixels(4.) }, "4px"), + ("5", quote! { pixels(5.) }, "5px"), + ("6", quote! { pixels(6.) }, "6px"), + ("7", quote! { pixels(7.) }, "7px"), + ("8", quote! { pixels(8.) }, "8px"), + ("9", quote! { pixels(9.) }, "9px"), + ("10", quote! { pixels(10.) }, "10px"), + ("11", quote! { pixels(11.) }, "11px"), + ("12", quote! { pixels(12.) }, "12px"), + ("16", quote! { pixels(16.) }, "16px"), + ("20", quote! { pixels(20.) }, "20px"), + ("24", quote! { pixels(24.) }, "24px"), + ("32", quote! { pixels(32.) }, "32px"), ] } diff --git a/crates/storybook/src/components.rs b/crates/storybook/src/components.rs index 1aafefc1a6..d07c2651a0 100644 --- a/crates/storybook/src/components.rs +++ b/crates/storybook/src/components.rs @@ -4,6 +4,12 @@ use gpui2::{ }; use std::{marker::PhantomData, rc::Rc}; +mod icon_button; +mod tab; + +pub(crate) use icon_button::{icon_button, ButtonVariant}; +pub(crate) use tab::tab; + struct ButtonHandlers { click: Option)>>, } diff --git a/crates/storybook/src/components/icon_button.rs b/crates/storybook/src/components/icon_button.rs new file mode 100644 index 0000000000..0a9b2ca285 --- /dev/null +++ b/crates/storybook/src/components/icon_button.rs @@ -0,0 +1,50 @@ +use crate::theme::theme; +use gpui2::elements::svg; +use gpui2::style::{StyleHelpers, Styleable}; +use gpui2::{elements::div, IntoElement}; +use gpui2::{Element, ParentElement, ViewContext}; + +#[derive(Element)] +pub(crate) struct IconButton { + path: &'static str, + variant: ButtonVariant, +} + +#[derive(PartialEq)] +pub enum ButtonVariant { + Ghost, + Filled, +} + +pub fn icon_button(path: &'static str, variant: ButtonVariant) -> impl Element { + IconButton { path, variant } +} + +impl IconButton { + fn render(&mut self, _: &mut V, cx: &mut ViewContext) -> impl IntoElement { + let theme = theme(cx); + + let mut div = div(); + if self.variant == ButtonVariant::Filled { + div = div.fill(theme.highest.on.default.background); + } + + div.w_7() + .h_6() + .flex() + .items_center() + .justify_center() + .rounded_md() + .hover() + .fill(theme.highest.base.hovered.background) + .active() + .fill(theme.highest.base.pressed.background) + .child( + svg() + .path(self.path) + .w_4() + .h_4() + .fill(theme.highest.variant.default.foreground), + ) + } +} diff --git a/crates/storybook/src/components/tab.rs b/crates/storybook/src/components/tab.rs new file mode 100644 index 0000000000..b945e113e5 --- /dev/null +++ b/crates/storybook/src/components/tab.rs @@ -0,0 +1,55 @@ +use crate::theme::theme; +use gpui2::style::{StyleHelpers, Styleable}; +use gpui2::{elements::div, IntoElement}; +use gpui2::{Element, ParentElement, ViewContext}; + +#[derive(Element)] +pub(crate) struct Tab { + title: &'static str, + enabled: bool, +} + +pub fn tab(title: &'static str, enabled: bool) -> impl Element { + Tab { title, enabled } +} + +impl Tab { + fn render(&mut self, _: &mut V, cx: &mut ViewContext) -> impl IntoElement { + let theme = theme(cx); + + div() + .px_2() + .py_0p5() + .flex() + .items_center() + .justify_center() + .rounded_lg() + .fill(if self.enabled { + theme.highest.on.default.background + } else { + theme.highest.base.default.background + }) + .hover() + .fill(if self.enabled { + theme.highest.on.hovered.background + } else { + theme.highest.base.hovered.background + }) + .active() + .fill(if self.enabled { + theme.highest.on.pressed.background + } else { + theme.highest.base.pressed.background + }) + .child( + div() + .text_sm() + .text_color(if self.enabled { + theme.highest.base.default.foreground + } else { + theme.highest.variant.default.foreground + }) + .child(self.title), + ) + } +} diff --git a/crates/storybook/src/modules.rs b/crates/storybook/src/modules.rs new file mode 100644 index 0000000000..bc8ba73b08 --- /dev/null +++ b/crates/storybook/src/modules.rs @@ -0,0 +1,3 @@ +mod tab_bar; + +pub(crate) use tab_bar::tab_bar; diff --git a/crates/storybook/src/modules/tab_bar.rs b/crates/storybook/src/modules/tab_bar.rs new file mode 100644 index 0000000000..06029c5dc2 --- /dev/null +++ b/crates/storybook/src/modules/tab_bar.rs @@ -0,0 +1,82 @@ +use std::marker::PhantomData; + +use crate::components::{icon_button, tab, ButtonVariant}; +use crate::theme::theme; +use gpui2::elements::div::ScrollState; +use gpui2::style::StyleHelpers; +use gpui2::{elements::div, IntoElement}; +use gpui2::{Element, ParentElement, ViewContext}; + +#[derive(Element)] +pub struct TabBar { + view_type: PhantomData, + scroll_state: ScrollState, +} + +pub fn tab_bar(scroll_state: ScrollState) -> TabBar { + TabBar { + view_type: PhantomData, + scroll_state, + } +} + +impl TabBar { + fn render(&mut self, _: &mut V, cx: &mut ViewContext) -> impl IntoElement { + let theme = theme(cx); + + div() + .w_full() + .flex() + // Left Side + .child( + div() + .px_1() + .flex() + .flex_none() + .gap_2() + // Nav Buttons + .child( + div() + .flex() + .items_center() + .gap_px() + .child(icon_button("icons/arrow_left.svg", ButtonVariant::Filled)) + .child(icon_button("icons/arrow_right.svg", ButtonVariant::Ghost)), + ), + ) + .child( + div().w_0().flex_1().h_full().child( + div() + .flex() + .gap_px() + .overflow_x_scroll(self.scroll_state.clone()) + .child(tab("Cargo.toml", false)) + .child(tab("Channels Panel", true)) + .child(tab("channels_panel.rs", false)) + .child(tab("workspace.rs", false)) + .child(tab("icon_button.rs", false)) + .child(tab("storybook.rs", false)) + .child(tab("theme.rs", false)) + .child(tab("theme_registry.rs", false)) + .child(tab("styleable_helpers.rs", false)), + ), + ) + // Right Side + .child( + div() + .px_1() + .flex() + .flex_none() + .gap_2() + // Nav Buttons + .child( + div() + .flex() + .items_center() + .gap_px() + .child(icon_button("icons/plus.svg", ButtonVariant::Ghost)) + .child(icon_button("icons/split.svg", ButtonVariant::Ghost)), + ), + ) + } +} diff --git a/crates/storybook/src/storybook.rs b/crates/storybook/src/storybook.rs index 04e1038988..1b40bc2dc4 100644 --- a/crates/storybook/src/storybook.rs +++ b/crates/storybook/src/storybook.rs @@ -12,6 +12,7 @@ use simplelog::SimpleLogger; mod collab_panel; mod components; mod element_ext; +mod modules; mod theme; mod workspace; @@ -34,13 +35,13 @@ fn main() { cx.add_window( gpui2::WindowOptions { - bounds: WindowBounds::Fixed(RectF::new(vec2f(0., 0.), vec2f(1400., 900.))), + bounds: WindowBounds::Fixed(RectF::new(vec2f(0., 0.), vec2f(1600., 900.))), center: true, ..Default::default() }, |cx| { view(|cx| { - cx.enable_inspector(); + // cx.enable_inspector(); storybook(&mut ViewContext::new(cx)) }) }, diff --git a/crates/storybook/src/workspace.rs b/crates/storybook/src/workspace.rs index d9f9c22fcb..c37b3f16ea 100644 --- a/crates/storybook/src/workspace.rs +++ b/crates/storybook/src/workspace.rs @@ -1,4 +1,4 @@ -use crate::{collab_panel::collab_panel, theme::theme}; +use crate::{collab_panel::collab_panel, modules::tab_bar, theme::theme}; use gpui2::{ elements::{div, div::ScrollState, img, svg}, style::{StyleHelpers, Styleable}, @@ -9,6 +9,7 @@ use gpui2::{ struct WorkspaceElement { left_scroll_state: ScrollState, right_scroll_state: ScrollState, + tab_bar_scroll_state: ScrollState, } pub fn workspace() -> impl Element { @@ -38,7 +39,19 @@ impl WorkspaceElement { .flex_row() .overflow_hidden() .child(collab_panel(self.left_scroll_state.clone())) - .child(div().h_full().flex_1()) + .child( + div() + .h_full() + .flex_1() + .fill(theme.highest.base.default.background) + .child( + div() + .flex() + .flex_col() + .flex_1() + .child(tab_bar(self.tab_bar_scroll_state.clone())), + ), + ) .child(collab_panel(self.right_scroll_state.clone())), ) .child(statusbar())