diff --git a/crates/gpui/src/elements/common.rs b/crates/gpui/src/elements/common.rs new file mode 100644 index 0000000000..0204be1c37 --- /dev/null +++ b/crates/gpui/src/elements/common.rs @@ -0,0 +1,114 @@ +use crate::{rgb, Hsla, Rgba, WindowAppearance}; + +#[derive(Debug, Default, Clone, Copy, PartialEq, Eq)] +/// The appearance of the base gpui colors, used to style gpui elements +/// +/// Varries based on the system's current [WindowAppearance]. +pub enum DefaultThemeAppearance { + #[default] + /// Use the set of colors for light appearances + Light, + /// Use the set of colors for dark appearances + Dark, +} + +impl From for DefaultThemeAppearance { + fn from(appearance: WindowAppearance) -> Self { + match appearance { + WindowAppearance::Light | WindowAppearance::VibrantLight => Self::Light, + WindowAppearance::Dark | WindowAppearance::VibrantDark => Self::Dark, + } + } +} + +/// Get the default colors for the given appearance +pub fn colors(appearance: DefaultThemeAppearance) -> DefaultColors { + match appearance { + DefaultThemeAppearance::Light => DefaultColors::light(), + DefaultThemeAppearance::Dark => DefaultColors::dark(), + } +} + +/// A collection of colors +#[derive(Debug, Clone, Copy, PartialEq)] +pub struct DefaultColors { + text: Rgba, + selected_text: Rgba, + background: Rgba, + disabled: Rgba, + selected: Rgba, + border: Rgba, + separator: Rgba, + container: Rgba, +} + +impl DefaultColors { + /// Get the default light colors + pub fn dark() -> Self { + Self { + text: rgb(0xFFFFFF), + selected_text: rgb(0xFFFFFF), + disabled: rgb(0x565656), + selected: rgb(0x2457CA), + background: rgb(0x222222), + border: rgb(0x000000), + separator: rgb(0xD9D9D9), + container: rgb(0x262626), + } + } + + /// Get the default dark colors + pub fn light() -> Self { + Self { + text: rgb(0x252525), + selected_text: rgb(0xFFFFFF), + background: rgb(0xFFFFFF), + disabled: rgb(0xB0B0B0), + selected: rgb(0x2A63D9), + border: rgb(0xD9D9D9), + separator: rgb(0xE6E6E6), + container: rgb(0xF4F5F5), + } + } +} + +/// A default gpui color +#[derive(Debug, Clone, Copy, PartialEq, Eq, strum::EnumIter)] +pub enum DefaultColor { + /// Text color + Text, + /// Selected text color + SelectedText, + /// Background color + Background, + /// Disabled color + Disabled, + /// Selected color + Selected, + /// Border color + Border, + /// Separator color + Separator, + /// Container color + Container, +} +impl DefaultColor { + /// Get the Rgb color for the given color type + pub fn color(&self, colors: &DefaultColors) -> Rgba { + match self { + DefaultColor::Text => colors.text, + DefaultColor::SelectedText => colors.selected_text, + DefaultColor::Background => colors.background, + DefaultColor::Disabled => colors.disabled, + DefaultColor::Selected => colors.selected, + DefaultColor::Border => colors.border, + DefaultColor::Separator => colors.separator, + DefaultColor::Container => colors.container, + } + } + + /// Get the Hsla color for the given color type + pub fn hsla(&self, colors: &DefaultColors) -> Hsla { + self.color(&colors).into() + } +} diff --git a/crates/gpui/src/elements/mod.rs b/crates/gpui/src/elements/mod.rs index 3387034180..0a680e4399 100644 --- a/crates/gpui/src/elements/mod.rs +++ b/crates/gpui/src/elements/mod.rs @@ -1,6 +1,7 @@ mod anchored; mod animation; mod canvas; +mod common; mod deferred; mod div; mod img; @@ -13,6 +14,7 @@ mod uniform_list; pub use anchored::*; pub use animation::*; pub use canvas::*; +pub use common::*; pub use deferred::*; pub use div::*; pub use img::*; diff --git a/crates/storybook/src/stories.rs b/crates/storybook/src/stories.rs index b824235b00..66881f741f 100644 --- a/crates/storybook/src/stories.rs +++ b/crates/storybook/src/stories.rs @@ -1,5 +1,6 @@ mod auto_height_editor; mod cursor; +mod default_colors; mod focus; mod kitchen_sink; mod overflow_scroll; @@ -11,6 +12,7 @@ mod with_rem_size; pub use auto_height_editor::*; pub use cursor::*; +pub use default_colors::*; pub use focus::*; pub use kitchen_sink::*; pub use overflow_scroll::*; diff --git a/crates/storybook/src/stories/default_colors.rs b/crates/storybook/src/stories/default_colors.rs new file mode 100644 index 0000000000..5e26272608 --- /dev/null +++ b/crates/storybook/src/stories/default_colors.rs @@ -0,0 +1,89 @@ +use gpui::{ + colors, div, prelude::*, DefaultColor, DefaultThemeAppearance, Hsla, Render, View, ViewContext, + WindowContext, +}; +use story::Story; +use strum::IntoEnumIterator; +use ui::{h_flex, ActiveTheme}; + +pub struct DefaultColorsStory; + +impl DefaultColorsStory { + pub fn view(cx: &mut WindowContext) -> View { + cx.new_view(|_cx| Self) + } +} + +impl Render for DefaultColorsStory { + fn render(&mut self, cx: &mut ViewContext) -> impl IntoElement { + let appearances = [DefaultThemeAppearance::Light, DefaultThemeAppearance::Dark]; + + Story::container() + .child(Story::title("Default Colors")) + .children(appearances.iter().map(|&appearance| { + let colors = colors(appearance); + let color_types = DefaultColor::iter() + .map(|color| { + let name = format!("{:?}", color); + let rgba = color.hsla(&colors); + (name, rgba) + }) + .collect::>(); + + div() + .flex() + .flex_col() + .gap_4() + .p_4() + .child(Story::label(format!("{:?} Appearance", appearance))) + .children(color_types.iter().map(|(name, color)| { + let color: Hsla = *color; + + div() + .flex() + .items_center() + .gap_2() + .child( + div() + .w_12() + .h_12() + .bg(color) + .border_1() + .border_color(cx.theme().colors().border), + ) + .child(Story::label(format!("{}: {:?}", name, color.clone()))) + })) + .child( + h_flex() + .gap_1() + .child( + h_flex() + .bg(DefaultColor::Background.hsla(&colors)) + .h_8() + .p_2() + .text_sm() + .text_color(DefaultColor::Text.hsla(&colors)) + .child("Default Text"), + ) + .child( + h_flex() + .bg(DefaultColor::Container.hsla(&colors)) + .h_8() + .p_2() + .text_sm() + .text_color(DefaultColor::Text.hsla(&colors)) + .child("Text on Container"), + ) + .child( + h_flex() + .bg(DefaultColor::Selected.hsla(&colors)) + .h_8() + .p_2() + .text_sm() + .text_color(DefaultColor::SelectedText.hsla(&colors)) + .child("Selected Text"), + ), + ) + })) + } +} diff --git a/crates/storybook/src/story_selector.rs b/crates/storybook/src/story_selector.rs index 7c875c4d90..5df02b1df2 100644 --- a/crates/storybook/src/story_selector.rs +++ b/crates/storybook/src/story_selector.rs @@ -20,6 +20,7 @@ pub enum ComponentStory { CollabNotification, ContextMenu, Cursor, + DefaultColors, Disclosure, Focus, Icon, @@ -54,6 +55,7 @@ impl ComponentStory { .into(), Self::ContextMenu => cx.new_view(|_| ui::ContextMenuStory).into(), Self::Cursor => cx.new_view(|_| crate::stories::CursorStory).into(), + Self::DefaultColors => DefaultColorsStory::view(cx).into(), Self::Disclosure => cx.new_view(|_| ui::DisclosureStory).into(), Self::Focus => FocusStory::view(cx).into(), Self::Icon => cx.new_view(|_| ui::IconStory).into(), @@ -64,15 +66,15 @@ impl ComponentStory { Self::ListHeader => cx.new_view(|_| ui::ListHeaderStory).into(), Self::ListItem => cx.new_view(|_| ui::ListItemStory).into(), Self::OverflowScroll => cx.new_view(|_| crate::stories::OverflowScrollStory).into(), + Self::Picker => PickerStory::new(cx).into(), Self::Scroll => ScrollStory::view(cx).into(), - Self::Text => TextStory::view(cx).into(), Self::Tab => cx.new_view(|_| ui::TabStory).into(), Self::TabBar => cx.new_view(|_| ui::TabBarStory).into(), + Self::Text => TextStory::view(cx).into(), Self::ToggleButton => cx.new_view(|_| ui::ToggleButtonStory).into(), Self::ToolStrip => cx.new_view(|_| ui::ToolStripStory).into(), Self::ViewportUnits => cx.new_view(|_| crate::stories::ViewportUnitsStory).into(), Self::WithRemSize => cx.new_view(|_| crate::stories::WithRemSizeStory).into(), - Self::Picker => PickerStory::new(cx).into(), } } }