diff --git a/crates/gpui3/src/styled.rs b/crates/gpui3/src/styled.rs index 56a1b68c75..d511198c65 100644 --- a/crates/gpui3/src/styled.rs +++ b/crates/gpui3/src/styled.rs @@ -1,6 +1,6 @@ use crate::{ self as gpui3, hsla, point, px, relative, rems, AlignItems, Display, Fill, FlexDirection, Hsla, - JustifyContent, Length, Position, SharedString, StyleRefinement, + JustifyContent, Length, Position, Rems, SharedString, StyleRefinement, }; use crate::{BoxShadow, TextStyleRefinement}; use smallvec::smallvec; @@ -350,6 +350,16 @@ pub trait Styled { self } + fn text_size(mut self, size: impl Into) -> Self + where + Self: Sized, + { + self.text_style() + .get_or_insert_with(Default::default) + .font_size = Some(size.into()); + self + } + fn text_xs(mut self) -> Self where Self: Sized, diff --git a/crates/ui2/src/components/list.rs b/crates/ui2/src/components/list.rs index 28d4e59d0c..8965c80811 100644 --- a/crates/ui2/src/components/list.rs +++ b/crates/ui2/src/components/list.rs @@ -3,10 +3,10 @@ use std::marker::PhantomData; use gpui3::{div, Div}; use crate::prelude::*; +use crate::settings::user_settings; use crate::theme::theme; use crate::{ - h_stack, token, v_stack, Avatar, Icon, IconColor, IconElement, IconSize, Label, LabelColor, - LabelSize, + h_stack, v_stack, Avatar, Icon, IconColor, IconElement, IconSize, Label, LabelColor, LabelSize, }; #[derive(Clone, Copy, Default, Debug, PartialEq)] @@ -94,7 +94,6 @@ impl ListHeader { fn render(&mut self, _view: &mut S, cx: &mut ViewContext) -> impl Element { let theme = theme(cx); - let token = token(); let system_color = SystemColor::new(); let color = ThemeColor::new(cx); @@ -166,7 +165,6 @@ impl ListSubHeader { fn render(&mut self, _view: &mut S, cx: &mut ViewContext) -> impl Element { let theme = theme(cx); - let token = token(); h_stack().flex_1().w_full().relative().py_1().child( div() @@ -351,7 +349,6 @@ impl ListEntry { cx: &mut ViewContext, ) -> Option> { let theme = theme(cx); - let token = token(); let disclosure_control_icon = if let Some(ToggleState::Toggled) = self.toggle { IconElement::new(Icon::ChevronDown) @@ -374,9 +371,9 @@ impl ListEntry { fn render(&mut self, _view: &mut S, cx: &mut ViewContext) -> impl Element { let theme = theme(cx); - let token = token(); let system_color = SystemColor::new(); let color = ThemeColor::new(cx); + let setting = user_settings(); let left_content = match self.left_content.clone() { Some(LeftContent::Icon(i)) => Some( @@ -408,7 +405,7 @@ impl ListEntry { // .ml(rems(0.75 * self.indent_level as f32)) .children((0..self.indent_level).map(|_| { div() - .w(token.list_indent_depth) + .w(*setting.list_indent_depth) .h_full() .flex() .justify_center() @@ -484,7 +481,6 @@ impl List { fn render(&mut self, _view: &mut S, cx: &mut ViewContext) -> impl Element { let theme = theme(cx); - let token = token(); let is_toggleable = self.toggleable != Toggleable::NotToggleable; let is_toggled = Toggleable::is_toggled(&self.toggleable); diff --git a/crates/ui2/src/components/panel.rs b/crates/ui2/src/components/panel.rs index 7aeb31aa37..52e36b2f14 100644 --- a/crates/ui2/src/components/panel.rs +++ b/crates/ui2/src/components/panel.rs @@ -3,8 +3,9 @@ use std::marker::PhantomData; use gpui3::{AbsoluteLength, AnyElement}; use smallvec::SmallVec; +use crate::settings::user_settings; +use crate::v_stack; use crate::{prelude::*, theme}; -use crate::{token, v_stack}; #[derive(Default, Debug, PartialEq, Eq, Hash, Clone, Copy)] pub enum PanelAllowedSides { @@ -53,14 +54,14 @@ pub struct Panel { impl Panel { pub fn new(scroll_state: ScrollState) -> Self { - let token = token(); + let setting = user_settings(); Self { state_type: PhantomData, scroll_state, current_side: PanelSide::default(), allowed_sides: PanelAllowedSides::default(), - initial_width: token.default_panel_size, + initial_width: *setting.default_panel_size, width: None, children: SmallVec::new(), } @@ -96,7 +97,6 @@ impl Panel { } fn render(&mut self, _view: &mut S, cx: &mut ViewContext) -> impl Element { - let token = token(); let theme = theme(cx); let panel_base; diff --git a/crates/ui2/src/components/title_bar.rs b/crates/ui2/src/components/title_bar.rs index 0613914476..f1d7d42711 100644 --- a/crates/ui2/src/components/title_bar.rs +++ b/crates/ui2/src/components/title_bar.rs @@ -4,6 +4,7 @@ use std::sync::Arc; use gpui3::{view, Context, View}; use crate::prelude::*; +use crate::settings::user_settings; use crate::{ random_players_with_call_status, theme, Avatar, Button, Icon, IconButton, IconColor, MicStatus, PlayerStack, PlayerWithCallStatus, ScreenShareStatus, ToolDivider, TrafficLights, @@ -93,6 +94,9 @@ impl TitleBar { fn render(&mut self, cx: &mut ViewContext) -> impl Element { let theme = theme(cx); + let color = ThemeColor::new(cx); + let setting = user_settings(); + // let has_focus = cx.window_is_active(); let has_focus = true; @@ -107,8 +111,7 @@ impl TitleBar { .items_center() .justify_between() .w_full() - .h_8() - .bg(theme.lowest.base.default.background) + .bg(color.background) .child( div() .flex() @@ -123,6 +126,9 @@ impl TitleBar { .flex() .items_center() .gap_1() + .when(*setting.titlebar.show_project_owner, |this| { + this.child(Button::new("iamnbutler")) + }) .child(Button::new("zed")) .child(Button::new("nate/gpui2-ui-components")), ) diff --git a/crates/ui2/src/components/traffic_lights.rs b/crates/ui2/src/components/traffic_lights.rs index cacc82bc08..0a2b769bca 100644 --- a/crates/ui2/src/components/traffic_lights.rs +++ b/crates/ui2/src/components/traffic_lights.rs @@ -1,7 +1,7 @@ use std::marker::PhantomData; use crate::prelude::*; -use crate::{theme, token, SystemColor}; +use crate::{theme, SystemColor}; #[derive(Clone, Copy)] enum TrafficLightColor { @@ -62,7 +62,6 @@ impl TrafficLights { fn render(&mut self, _view: &mut S, cx: &mut ViewContext) -> impl Element { let theme = theme(cx); - let token = token(); div() .flex() diff --git a/crates/ui2/src/elements/button.rs b/crates/ui2/src/elements/button.rs index ce7edd2a78..b4d9d8afa6 100644 --- a/crates/ui2/src/elements/button.rs +++ b/crates/ui2/src/elements/button.rs @@ -1,9 +1,11 @@ use std::marker::PhantomData; use std::sync::Arc; +use gpui3::rems; use gpui3::{DefiniteLength, Hsla, Interactive, MouseButton, WindowContext}; use crate::prelude::*; +use crate::settings::user_settings; use crate::{h_stack, Icon, IconColor, IconElement, Label, LabelColor, LabelSize}; #[derive(Default, PartialEq, Clone, Copy)] @@ -148,11 +150,11 @@ impl Button { fn render(&mut self, _view: &mut S, cx: &mut ViewContext) -> impl Element { let icon_color = self.icon_color(); let border_color = self.border_color(cx); + let setting = user_settings(); let mut el = h_stack() - .h_6() - .px_1() - .items_center() + .p_1() + .text_size(ui_size(1.125)) .rounded_md() .border() .border_color(border_color) diff --git a/crates/ui2/src/lib.rs b/crates/ui2/src/lib.rs index 51489173ad..417a77fabe 100644 --- a/crates/ui2/src/lib.rs +++ b/crates/ui2/src/lib.rs @@ -4,6 +4,7 @@ mod components; mod element_ext; mod elements; pub mod prelude; +mod settings; mod static_data; mod theme; diff --git a/crates/ui2/src/prelude.rs b/crates/ui2/src/prelude.rs index 44ca262470..db484b6cfa 100644 --- a/crates/ui2/src/prelude.rs +++ b/crates/ui2/src/prelude.rs @@ -3,40 +3,35 @@ pub use gpui3::{ ViewContext, WindowContext, }; +use crate::settings::user_settings; pub use crate::{theme, ButtonVariant, ElementExt, Theme}; -use gpui3::{hsla, rems, rgb, AbsoluteLength, Hsla}; +use gpui3::{hsla, rems, rgb, AbsoluteLength, Hsla, Rems}; use strum::EnumIter; #[derive(Clone, Copy)] -pub struct Token { +pub struct FakeSettings { pub list_indent_depth: AbsoluteLength, pub default_panel_size: AbsoluteLength, - pub state_hover_background: Hsla, - pub state_active_background: Hsla, } -impl Default for Token { +impl Default for FakeSettings { fn default() -> Self { Self { list_indent_depth: rems(0.3).into(), default_panel_size: AbsoluteLength::Rems(rems(16.)), - state_hover_background: hsla(0.0, 0.0, 0.0, 0.08), - state_active_background: hsla(0.0, 0.0, 0.0, 0.16), } } } -pub fn token() -> Token { - Token::default() -} - #[derive(Default)] pub struct SystemColor { pub transparent: Hsla, pub mac_os_traffic_light_red: Hsla, pub mac_os_traffic_light_yellow: Hsla, pub mac_os_traffic_light_green: Hsla, + pub state_hover_background: Hsla, + pub state_active_background: Hsla, } impl SystemColor { @@ -46,6 +41,8 @@ impl SystemColor { mac_os_traffic_light_red: rgb::(0xEC695E), mac_os_traffic_light_yellow: rgb::(0xF4BF4F), mac_os_traffic_light_green: rgb::(0x62C554), + state_hover_background: hsla(0.0, 0.0, 0.0, 0.08), + state_active_background: hsla(0.0, 0.0, 0.0, 0.16), } } pub fn color(&self) -> Hsla { @@ -62,6 +59,8 @@ pub struct ThemeColor { /// The background color of an elevated surface, like a modal, tooltip or toast. pub elevated_surface: Hsla, pub surface: Hsla, + /// Window background color + pub background: Hsla, /// Default background for elements like filled buttons, /// text fields, checkboxes, radio buttons, etc. /// - TODO: Map to step 3. @@ -99,6 +98,7 @@ impl ThemeColor { border_transparent: system_color.transparent, elevated_surface: theme.middle.base.default.background, surface: theme.middle.base.default.background, + background: theme.lowest.base.default.background, filled_element: theme.lowest.base.default.background, filled_element_hover: theme.lowest.base.hovered.background, filled_element_active: theme.lowest.base.active.background, @@ -157,6 +157,12 @@ impl HighlightColor { } } +pub fn ui_size(size: f32) -> Rems { + let setting = user_settings(); + + rems(*setting.ui_scale * size) +} + #[derive(Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Copy, EnumIter)] pub enum FileSystemStatus { #[default] @@ -251,6 +257,23 @@ pub enum DisclosureControlVisibility { Always, } +#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Copy, EnumIter)] +pub enum DisclosureControlStyle { + /// Shows the disclosure control only when hovered where possible. + /// + /// More compact, but not available everywhere. + ChevronOnHover, + /// Shows an icon where possible, otherwise shows a chevron. + /// + /// For example, in a file tree a folder or file icon is shown + /// instead of a chevron + Icon, + /// Always shows a chevron. + Chevron, + /// Completely hides the disclosure control where possible. + None, +} + #[derive(Default, PartialEq, Copy, Clone, EnumIter, strum::Display)] pub enum InteractionState { #[default] diff --git a/crates/ui2/src/settings.rs b/crates/ui2/src/settings.rs new file mode 100644 index 0000000000..a387b8ddd9 --- /dev/null +++ b/crates/ui2/src/settings.rs @@ -0,0 +1,70 @@ +use std::ops::Deref; + +use gpui3::{rems, AbsoluteLength}; + +use crate::DisclosureControlStyle; + +// This is a fake static example of user settings overriding the default settings +pub fn user_settings() -> Settings { + let mut settings = Settings::default(); + settings.list_indent_depth = SettingValue::UserDefined(rems(0.5).into()); + settings +} + +#[derive(Clone)] +pub enum SettingValue { + UserDefined(T), + Default(T), +} + +impl Deref for SettingValue { + type Target = T; + + fn deref(&self) -> &Self::Target { + match self { + Self::UserDefined(value) => value, + Self::Default(value) => value, + } + } +} + +#[derive(Clone)] +pub struct TitlebarSettings { + pub show_project_owner: SettingValue, + pub show_git_status: SettingValue, + pub show_git_controls: SettingValue, +} + +impl Default for TitlebarSettings { + fn default() -> Self { + Self { + show_project_owner: SettingValue::Default(true), + show_git_status: SettingValue::Default(true), + show_git_controls: SettingValue::Default(true), + } + } +} + +// These should be merged into settings +#[derive(Clone)] +pub struct Settings { + pub default_panel_size: SettingValue, + pub list_disclosure_style: SettingValue, + pub list_indent_depth: SettingValue, + pub titlebar: TitlebarSettings, + pub ui_scale: SettingValue, +} + +impl Default for Settings { + fn default() -> Self { + Self { + titlebar: TitlebarSettings::default(), + list_disclosure_style: SettingValue::Default(DisclosureControlStyle::ChevronOnHover), + list_indent_depth: SettingValue::Default(rems(0.3).into()), + default_panel_size: SettingValue::Default(rems(16.).into()), + ui_scale: SettingValue::Default(1.), + } + } +} + +impl Settings {}