diff --git a/crates/assistant/src/assistant_panel.rs b/crates/assistant/src/assistant_panel.rs index 15f9e5c59d..20e6347d01 100644 --- a/crates/assistant/src/assistant_panel.rs +++ b/crates/assistant/src/assistant_panel.rs @@ -77,7 +77,7 @@ use ui::TintColor; use ui::{ prelude::*, utils::{format_distance_from_now, DateTimeType}, - Avatar, AvatarShape, ButtonLike, ContextMenu, Disclosure, ElevationIndex, KeyBinding, ListItem, + Avatar, ButtonLike, ContextMenu, Disclosure, ElevationIndex, KeyBinding, ListItem, ListItemSpacing, PopoverMenu, PopoverMenuHandle, Tooltip, }; use util::{maybe, ResultExt}; @@ -262,9 +262,7 @@ impl PickerDelegate for SavedContextPickerDelegate { .gap_2() .children(if let Some(host_user) = host_user { vec![ - Avatar::new(host_user.avatar_uri.clone()) - .shape(AvatarShape::Circle) - .into_any_element(), + Avatar::new(host_user.avatar_uri.clone()).into_any_element(), Label::new(format!("Shared by @{}", host_user.github_login)) .color(Color::Muted) .size(LabelSize::Small) diff --git a/crates/assistant/src/prompt_library.rs b/crates/assistant/src/prompt_library.rs index 24e20a18a7..6c43579d6e 100644 --- a/crates/assistant/src/prompt_library.rs +++ b/crates/assistant/src/prompt_library.rs @@ -910,7 +910,7 @@ impl PromptLibrary { .features .clone(), font_size: HeadlineSize::Large - .size() + .rems() .into(), font_weight: settings.ui_font.weight, line_height: relative( diff --git a/crates/storybook/src/stories/with_rem_size.rs b/crates/storybook/src/stories/with_rem_size.rs index 11add24955..558dab6c54 100644 --- a/crates/storybook/src/stories/with_rem_size.rs +++ b/crates/storybook/src/stories/with_rem_size.rs @@ -1,7 +1,7 @@ use gpui::{AnyElement, Hsla, Render}; use story::Story; -use ui::{prelude::*, WithRemSize}; +use ui::{prelude::*, utils::WithRemSize}; pub struct WithRemSizeStory; diff --git a/crates/ui/src/components/avatar/avatar.rs b/crates/ui/src/components/avatar/avatar.rs index 27cf86a01f..4106b17452 100644 --- a/crates/ui/src/components/avatar/avatar.rs +++ b/crates/ui/src/components/avatar/avatar.rs @@ -2,16 +2,6 @@ use crate::prelude::*; use gpui::{img, AnyElement, Hsla, ImageSource, Img, IntoElement, Styled}; -/// The shape of an [`Avatar`]. -#[derive(Debug, Default, PartialEq, Clone)] -pub enum AvatarShape { - /// The avatar is shown in a circle. - #[default] - Circle, - /// The avatar is shown in a rectangle with rounded corners. - RoundedRectangle, -} - /// An element that renders a user avatar with customizable appearance options. /// /// # Examples @@ -20,7 +10,6 @@ pub enum AvatarShape { /// use ui::{Avatar, AvatarShape}; /// /// Avatar::new("path/to/image.png") -/// .shape(AvatarShape::Circle) /// .grayscale(true) /// .border_color(gpui::red()); /// ``` @@ -33,6 +22,7 @@ pub struct Avatar { } impl Avatar { + /// Creates a new avatar element with the specified image source. pub fn new(src: impl Into) -> Self { Avatar { image: img(src), @@ -42,26 +32,6 @@ impl Avatar { } } - /// Sets the shape of the avatar image. - /// - /// This method allows the shape of the avatar to be specified using an [`AvatarShape`]. - /// It modifies the corner radius of the image to match the specified shape. - /// - /// # Examples - /// - /// ``` - /// use ui::{Avatar, AvatarShape}; - /// - /// Avatar::new("path/to/image.png").shape(AvatarShape::Circle); - /// ``` - pub fn shape(mut self, shape: AvatarShape) -> Self { - self.image = match shape { - AvatarShape::Circle => self.image.rounded_full(), - AvatarShape::RoundedRectangle => self.image.rounded_md(), - }; - self - } - /// Applies a grayscale filter to the avatar image. /// /// # Examples @@ -76,6 +46,11 @@ impl Avatar { self } + /// Sets the border color of the avatar. + /// + /// This might be used to match the border to the background color of + /// the parent element to create the illusion of cropping another + /// shape underneath (for example in face piles.) pub fn border_color(mut self, color: impl Into) -> Self { self.border_color = Some(color.into()); self @@ -87,6 +62,7 @@ impl Avatar { self } + /// Sets the current indicator to be displayed on the avatar, if any. pub fn indicator(mut self, indicator: impl Into>) -> Self { self.indicator = indicator.into().map(IntoElement::into_any_element); self @@ -95,10 +71,6 @@ impl Avatar { impl RenderOnce for Avatar { fn render(mut self, cx: &mut WindowContext) -> impl IntoElement { - if self.image.style().corner_radii.top_left.is_none() { - self = self.shape(AvatarShape::Circle); - } - let border_width = if self.border_color.is_some() { px(2.) } else { diff --git a/crates/ui/src/components/avatar/avatar_audio_status_indicator.rs b/crates/ui/src/components/avatar/avatar_audio_status_indicator.rs index e249727a0c..8ff6491db7 100644 --- a/crates/ui/src/components/avatar/avatar_audio_status_indicator.rs +++ b/crates/ui/src/components/avatar/avatar_audio_status_indicator.rs @@ -2,12 +2,17 @@ use gpui::AnyView; use crate::prelude::*; +/// The audio status of an player, for use in representing +/// their status visually on their avatar. #[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Copy)] pub enum AudioStatus { + /// The player's microphone is muted. Muted, + /// The player's microphone is muted, and collaboration audio is disabled. Deafened, } +/// An indicator that shows the audio status of a player. #[derive(IntoElement)] pub struct AvatarAudioStatusIndicator { audio_status: AudioStatus, @@ -15,6 +20,7 @@ pub struct AvatarAudioStatusIndicator { } impl AvatarAudioStatusIndicator { + /// Creates a new `AvatarAudioStatusIndicator` pub fn new(audio_status: AudioStatus) -> Self { Self { audio_status, @@ -22,6 +28,7 @@ impl AvatarAudioStatusIndicator { } } + /// Sets the tooltip for the indicator. pub fn tooltip(mut self, tooltip: impl Fn(&mut WindowContext) -> AnyView + 'static) -> Self { self.tooltip = Some(Box::new(tooltip)); self diff --git a/crates/ui/src/components/avatar/avatar_availability_indicator.rs b/crates/ui/src/components/avatar/avatar_availability_indicator.rs index 3e4f9b2d1b..4690f8fccd 100644 --- a/crates/ui/src/components/avatar/avatar_availability_indicator.rs +++ b/crates/ui/src/components/avatar/avatar_availability_indicator.rs @@ -1,3 +1,4 @@ +#![allow(missing_docs)] use crate::prelude::*; #[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Copy)] diff --git a/crates/ui/src/components/button/button.rs b/crates/ui/src/components/button/button.rs index 1e11d25cc6..f81de83a2b 100644 --- a/crates/ui/src/components/button/button.rs +++ b/crates/ui/src/components/button/button.rs @@ -1,3 +1,4 @@ +#![allow(missing_docs)] use gpui::{AnyView, DefiniteLength}; use crate::{prelude::*, ElevationIndex, IconPosition, KeyBinding, Spacing}; diff --git a/crates/ui/src/components/button/button_icon.rs b/crates/ui/src/components/button/button_icon.rs index 54ca0f7921..f3aebe7f76 100644 --- a/crates/ui/src/components/button/button_icon.rs +++ b/crates/ui/src/components/button/button_icon.rs @@ -1,3 +1,4 @@ +#![allow(missing_docs)] use crate::{prelude::*, Icon, IconName, IconSize}; /// An icon that appears within a button. diff --git a/crates/ui/src/components/button/button_like.rs b/crates/ui/src/components/button/button_like.rs index a22c27d241..22e8421391 100644 --- a/crates/ui/src/components/button/button_like.rs +++ b/crates/ui/src/components/button/button_like.rs @@ -1,8 +1,9 @@ +#![allow(missing_docs)] use gpui::{relative, CursorStyle, DefiniteLength, MouseButton}; use gpui::{transparent_black, AnyElement, AnyView, ClickEvent, Hsla, Rems}; use smallvec::SmallVec; -use crate::{prelude::*, Elevation, ElevationIndex, Spacing}; +use crate::{prelude::*, ElevationIndex, Spacing}; /// A trait for buttons that can be Selected. Enables setting the [`ButtonStyle`] of a button when it is selected. pub trait SelectableButton: Selectable { @@ -145,20 +146,12 @@ pub(crate) struct ButtonLikeStyles { pub icon_color: Hsla, } -fn element_bg_from_elevation(elevation: Option, cx: &mut WindowContext) -> Hsla { +fn element_bg_from_elevation(elevation: Option, cx: &mut WindowContext) -> Hsla { match elevation { - Some(Elevation::ElevationIndex(ElevationIndex::Background)) => { - cx.theme().colors().element_background - } - Some(Elevation::ElevationIndex(ElevationIndex::ElevatedSurface)) => { - cx.theme().colors().surface_background - } - Some(Elevation::ElevationIndex(ElevationIndex::Surface)) => { - cx.theme().colors().elevated_surface_background - } - Some(Elevation::ElevationIndex(ElevationIndex::ModalSurface)) => { - cx.theme().colors().background - } + Some(ElevationIndex::Background) => cx.theme().colors().element_background, + Some(ElevationIndex::ElevatedSurface) => cx.theme().colors().surface_background, + Some(ElevationIndex::Surface) => cx.theme().colors().elevated_surface_background, + Some(ElevationIndex::ModalSurface) => cx.theme().colors().background, _ => cx.theme().colors().element_background, } } @@ -166,7 +159,7 @@ fn element_bg_from_elevation(elevation: Option, cx: &mut WindowContex impl ButtonStyle { pub(crate) fn enabled( self, - elevation: Option, + elevation: Option, cx: &mut WindowContext, ) -> ButtonLikeStyles { let filled_background = element_bg_from_elevation(elevation, cx); @@ -196,7 +189,7 @@ impl ButtonStyle { pub(crate) fn hovered( self, - elevation: Option, + elevation: Option, cx: &mut WindowContext, ) -> ButtonLikeStyles { let mut filled_background = element_bg_from_elevation(elevation, cx); @@ -281,7 +274,7 @@ impl ButtonStyle { #[allow(unused)] pub(crate) fn disabled( self, - elevation: Option, + elevation: Option, cx: &mut WindowContext, ) -> ButtonLikeStyles { element_bg_from_elevation(elevation, cx).fade_out(0.82); @@ -348,7 +341,7 @@ pub struct ButtonLike { pub(super) selected_style: Option, pub(super) width: Option, pub(super) height: Option, - pub(super) layer: Option, + pub(super) layer: Option, size: ButtonSize, rounding: Option, tooltip: Option AnyView>>, @@ -463,7 +456,7 @@ impl ButtonCommon for ButtonLike { } fn layer(mut self, elevation: ElevationIndex) -> Self { - self.layer = Some(elevation.into()); + self.layer = Some(elevation); self } } diff --git a/crates/ui/src/components/button/icon_button.rs b/crates/ui/src/components/button/icon_button.rs index cf564efabb..bad10d6fb4 100644 --- a/crates/ui/src/components/button/icon_button.rs +++ b/crates/ui/src/components/button/icon_button.rs @@ -1,3 +1,4 @@ +#![allow(missing_docs)] use gpui::{AnyView, DefiniteLength}; use super::button_like::{ButtonCommon, ButtonLike, ButtonSize, ButtonStyle}; diff --git a/crates/ui/src/components/button/toggle_button.rs b/crates/ui/src/components/button/toggle_button.rs index 3ad47ed166..33577fc4e8 100644 --- a/crates/ui/src/components/button/toggle_button.rs +++ b/crates/ui/src/components/button/toggle_button.rs @@ -1,3 +1,4 @@ +#![allow(missing_docs)] use gpui::{AnyView, ClickEvent}; use crate::{prelude::*, ButtonLike, ButtonLikeRounding, ElevationIndex}; diff --git a/crates/ui/src/components/checkbox.rs b/crates/ui/src/components/checkbox.rs index d750d6c036..d3c4d377ae 100644 --- a/crates/ui/src/components/checkbox.rs +++ b/crates/ui/src/components/checkbox.rs @@ -1,3 +1,4 @@ +#![allow(missing_docs)] mod checkbox_with_label; pub use checkbox_with_label::*; diff --git a/crates/ui/src/components/checkbox/checkbox.rs b/crates/ui/src/components/checkbox/checkbox.rs index cd1ea97ea9..472bfb23f1 100644 --- a/crates/ui/src/components/checkbox/checkbox.rs +++ b/crates/ui/src/components/checkbox/checkbox.rs @@ -1,3 +1,5 @@ +#![allow(missing_docs)] + use gpui::{div, prelude::*, ElementId, IntoElement, Styled, WindowContext}; use crate::prelude::*; diff --git a/crates/ui/src/components/checkbox/checkbox_with_label.rs b/crates/ui/src/components/checkbox/checkbox_with_label.rs index 2cf8fc2832..2b92e47938 100644 --- a/crates/ui/src/components/checkbox/checkbox_with_label.rs +++ b/crates/ui/src/components/checkbox/checkbox_with_label.rs @@ -1,3 +1,5 @@ +#![allow(missing_docs)] + use std::sync::Arc; use crate::{prelude::*, Checkbox}; diff --git a/crates/ui/src/components/context_menu.rs b/crates/ui/src/components/context_menu.rs index 644cb1dd24..92884b0182 100644 --- a/crates/ui/src/components/context_menu.rs +++ b/crates/ui/src/components/context_menu.rs @@ -1,6 +1,7 @@ +#![allow(missing_docs)] use crate::{ - h_flex, prelude::*, v_flex, Icon, IconName, KeyBinding, Label, List, ListItem, ListSeparator, - ListSubHeader, WithRemSize, + h_flex, prelude::*, utils::WithRemSize, v_flex, Icon, IconName, KeyBinding, Label, List, + ListItem, ListSeparator, ListSubHeader, }; use gpui::{ px, Action, AnyElement, AppContext, DismissEvent, EventEmitter, FocusHandle, FocusableView, diff --git a/crates/ui/src/components/disclosure.rs b/crates/ui/src/components/disclosure.rs index 41ff0a4c3a..9e8ab48221 100644 --- a/crates/ui/src/components/disclosure.rs +++ b/crates/ui/src/components/disclosure.rs @@ -1,3 +1,4 @@ +#![allow(missing_docs)] use std::sync::Arc; use gpui::{ClickEvent, CursorStyle}; diff --git a/crates/ui/src/components/divider.rs b/crates/ui/src/components/divider.rs index 772fc1a81a..71234057b2 100644 --- a/crates/ui/src/components/divider.rs +++ b/crates/ui/src/components/divider.rs @@ -1,3 +1,4 @@ +#![allow(missing_docs)] use gpui::{Hsla, IntoElement}; use crate::prelude::*; diff --git a/crates/ui/src/components/dropdown_menu.rs b/crates/ui/src/components/dropdown_menu.rs index ab2f6a372e..8d930a63ac 100644 --- a/crates/ui/src/components/dropdown_menu.rs +++ b/crates/ui/src/components/dropdown_menu.rs @@ -1,3 +1,4 @@ +#![allow(missing_docs)] use gpui::{AnchorCorner, ClickEvent, CursorStyle, MouseButton, View}; use crate::{prelude::*, ContextMenu, PopoverMenu}; diff --git a/crates/ui/src/components/facepile.rs b/crates/ui/src/components/facepile.rs index f391fc60bb..c3a56d8e20 100644 --- a/crates/ui/src/components/facepile.rs +++ b/crates/ui/src/components/facepile.rs @@ -1,3 +1,4 @@ +#![allow(missing_docs)] use crate::prelude::*; use gpui::{AnyElement, StyleRefinement}; use smallvec::SmallVec; diff --git a/crates/ui/src/components/icon.rs b/crates/ui/src/components/icon.rs index 323181e841..693caaaafd 100644 --- a/crates/ui/src/components/icon.rs +++ b/crates/ui/src/components/icon.rs @@ -1,3 +1,4 @@ +#![allow(missing_docs)] use gpui::{svg, AnimationElement, Hsla, IntoElement, Rems, Transformation}; use serde::{Deserialize, Serialize}; use strum::{EnumIter, EnumString, IntoStaticStr}; diff --git a/crates/ui/src/components/image.rs b/crates/ui/src/components/image.rs index e7eefe5fea..a510b4d7a2 100644 --- a/crates/ui/src/components/image.rs +++ b/crates/ui/src/components/image.rs @@ -1,3 +1,4 @@ +#![allow(missing_docs)] use gpui::{svg, IntoElement, Rems, RenderOnce, Size, Styled, WindowContext}; use serde::{Deserialize, Serialize}; use strum::{EnumIter, EnumString, IntoStaticStr}; diff --git a/crates/ui/src/components/indicator.rs b/crates/ui/src/components/indicator.rs index 0b4a3147c1..009fe44dfe 100644 --- a/crates/ui/src/components/indicator.rs +++ b/crates/ui/src/components/indicator.rs @@ -1,3 +1,4 @@ +#![allow(missing_docs)] use crate::{prelude::*, AnyIcon}; #[derive(Default)] diff --git a/crates/ui/src/components/keybinding.rs b/crates/ui/src/components/keybinding.rs index 1e4983f5ad..135599b914 100644 --- a/crates/ui/src/components/keybinding.rs +++ b/crates/ui/src/components/keybinding.rs @@ -1,5 +1,7 @@ +#![allow(missing_docs)] +use crate::PlatformStyle; use crate::{h_flex, prelude::*, Icon, IconName, IconSize}; -use gpui::{relative, Action, FocusHandle, IntoElement, Keystroke}; +use gpui::{relative, Action, FocusHandle, IntoElement, Keystroke, WindowContext}; #[derive(IntoElement, Clone)] pub struct KeyBinding { @@ -192,3 +194,173 @@ impl KeyIcon { Self { icon } } } + +/// Returns a textual representation of the key binding for the given [`Action`]. +pub fn text_for_action(action: &dyn Action, cx: &mut WindowContext) -> Option { + let key_binding = cx.bindings_for_action(action).last().cloned()?; + Some(text_for_key_binding(key_binding, PlatformStyle::platform())) +} + +/// Returns a textual representation of the key binding for the given [`Action`] +/// as if the provided [`FocusHandle`] was focused. +pub fn text_for_action_in( + action: &dyn Action, + focus: &FocusHandle, + cx: &mut WindowContext, +) -> Option { + let key_binding = cx.bindings_for_action_in(action, focus).last().cloned()?; + Some(text_for_key_binding(key_binding, PlatformStyle::platform())) +} + +/// Returns a textual representation of the given key binding for the specified platform. +pub fn text_for_key_binding( + key_binding: gpui::KeyBinding, + platform_style: PlatformStyle, +) -> String { + key_binding + .keystrokes() + .iter() + .map(|keystroke| text_for_keystroke(keystroke, platform_style)) + .collect::>() + .join(" ") +} + +/// Returns a textual representation of the given [`Keystroke`]. +pub fn text_for_keystroke(keystroke: &Keystroke, platform_style: PlatformStyle) -> String { + let mut text = String::new(); + + let delimiter = match platform_style { + PlatformStyle::Mac => '-', + PlatformStyle::Linux | PlatformStyle::Windows => '+', + }; + + if keystroke.modifiers.function { + match platform_style { + PlatformStyle::Mac => text.push_str("fn"), + PlatformStyle::Linux | PlatformStyle::Windows => text.push_str("Fn"), + } + + text.push(delimiter); + } + + if keystroke.modifiers.control { + match platform_style { + PlatformStyle::Mac => text.push_str("Control"), + PlatformStyle::Linux | PlatformStyle::Windows => text.push_str("Ctrl"), + } + + text.push(delimiter); + } + + if keystroke.modifiers.alt { + match platform_style { + PlatformStyle::Mac => text.push_str("Option"), + PlatformStyle::Linux | PlatformStyle::Windows => text.push_str("Alt"), + } + + text.push(delimiter); + } + + if keystroke.modifiers.platform { + match platform_style { + PlatformStyle::Mac => text.push_str("Command"), + PlatformStyle::Linux => text.push_str("Super"), + PlatformStyle::Windows => text.push_str("Win"), + } + + text.push(delimiter); + } + + if keystroke.modifiers.shift { + match platform_style { + PlatformStyle::Mac | PlatformStyle::Linux | PlatformStyle::Windows => { + text.push_str("Shift") + } + } + + text.push(delimiter); + } + + fn capitalize(str: &str) -> String { + let mut chars = str.chars(); + match chars.next() { + None => String::new(), + Some(first_char) => first_char.to_uppercase().collect::() + chars.as_str(), + } + } + + let key = match keystroke.key.as_str() { + "pageup" => "PageUp", + "pagedown" => "PageDown", + key => &capitalize(key), + }; + + text.push_str(key); + + text +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_text_for_keystroke() { + assert_eq!( + text_for_keystroke(&Keystroke::parse("cmd-c").unwrap(), PlatformStyle::Mac), + "Command-C".to_string() + ); + assert_eq!( + text_for_keystroke(&Keystroke::parse("cmd-c").unwrap(), PlatformStyle::Linux), + "Super+C".to_string() + ); + assert_eq!( + text_for_keystroke(&Keystroke::parse("cmd-c").unwrap(), PlatformStyle::Windows), + "Win+C".to_string() + ); + + assert_eq!( + text_for_keystroke( + &Keystroke::parse("ctrl-alt-delete").unwrap(), + PlatformStyle::Mac + ), + "Control-Option-Delete".to_string() + ); + assert_eq!( + text_for_keystroke( + &Keystroke::parse("ctrl-alt-delete").unwrap(), + PlatformStyle::Linux + ), + "Ctrl+Alt+Delete".to_string() + ); + assert_eq!( + text_for_keystroke( + &Keystroke::parse("ctrl-alt-delete").unwrap(), + PlatformStyle::Windows + ), + "Ctrl+Alt+Delete".to_string() + ); + + assert_eq!( + text_for_keystroke( + &Keystroke::parse("shift-pageup").unwrap(), + PlatformStyle::Mac + ), + "Shift-PageUp".to_string() + ); + assert_eq!( + text_for_keystroke( + &Keystroke::parse("shift-pageup").unwrap(), + PlatformStyle::Linux + ), + "Shift+PageUp".to_string() + ); + assert_eq!( + text_for_keystroke( + &Keystroke::parse("shift-pageup").unwrap(), + PlatformStyle::Windows + ), + "Shift+PageUp".to_string() + ); + } +} diff --git a/crates/ui/src/components/label/highlighted_label.rs b/crates/ui/src/components/label/highlighted_label.rs index 6b170bb810..f961713956 100644 --- a/crates/ui/src/components/label/highlighted_label.rs +++ b/crates/ui/src/components/label/highlighted_label.rs @@ -1,3 +1,5 @@ +#![allow(missing_docs)] + use std::ops::Range; use gpui::{FontWeight, HighlightStyle, StyledText}; diff --git a/crates/ui/src/components/label/label.rs b/crates/ui/src/components/label/label.rs index 898a59de77..f655961841 100644 --- a/crates/ui/src/components/label/label.rs +++ b/crates/ui/src/components/label/label.rs @@ -1,3 +1,5 @@ +#![allow(missing_docs)] + use gpui::{StyleRefinement, WindowContext}; use crate::{prelude::*, LabelCommon, LabelLike, LabelSize, LineHeightStyle}; diff --git a/crates/ui/src/components/label/label_like.rs b/crates/ui/src/components/label/label_like.rs index bc2fae15a7..0bd21eda4f 100644 --- a/crates/ui/src/components/label/label_like.rs +++ b/crates/ui/src/components/label/label_like.rs @@ -1,3 +1,5 @@ +#![allow(missing_docs)] + use gpui::{relative, AnyElement, FontWeight, StyleRefinement, Styled, UnderlineStyle}; use settings::Settings; use smallvec::SmallVec; diff --git a/crates/ui/src/components/list/list.rs b/crates/ui/src/components/list/list.rs index 4bf157ef40..e112a558ee 100644 --- a/crates/ui/src/components/list/list.rs +++ b/crates/ui/src/components/list/list.rs @@ -1,3 +1,5 @@ +#![allow(missing_docs)] + use gpui::AnyElement; use smallvec::SmallVec; diff --git a/crates/ui/src/components/list/list_header.rs b/crates/ui/src/components/list/list_header.rs index 3b15f8cd3d..b69426b6d1 100644 --- a/crates/ui/src/components/list/list_header.rs +++ b/crates/ui/src/components/list/list_header.rs @@ -1,3 +1,5 @@ +#![allow(missing_docs)] + use std::sync::Arc; use crate::{h_flex, prelude::*, Disclosure, Label}; diff --git a/crates/ui/src/components/list/list_item.rs b/crates/ui/src/components/list/list_item.rs index e13fb8ef26..37076737a6 100644 --- a/crates/ui/src/components/list/list_item.rs +++ b/crates/ui/src/components/list/list_item.rs @@ -1,3 +1,5 @@ +#![allow(missing_docs)] + use std::sync::Arc; use gpui::{px, AnyElement, AnyView, ClickEvent, MouseButton, MouseDownEvent, Pixels}; diff --git a/crates/ui/src/components/list/list_separator.rs b/crates/ui/src/components/list/list_separator.rs index 0d5fdf8d49..aa53efab37 100644 --- a/crates/ui/src/components/list/list_separator.rs +++ b/crates/ui/src/components/list/list_separator.rs @@ -1,3 +1,5 @@ +#![allow(missing_docs)] + use crate::prelude::*; #[derive(IntoElement)] diff --git a/crates/ui/src/components/list/list_sub_header.rs b/crates/ui/src/components/list/list_sub_header.rs index 0ed072ebbf..25132b7668 100644 --- a/crates/ui/src/components/list/list_sub_header.rs +++ b/crates/ui/src/components/list/list_sub_header.rs @@ -1,3 +1,5 @@ +#![allow(missing_docs)] + use crate::prelude::*; use crate::{h_flex, Icon, IconName, IconSize, Label}; diff --git a/crates/ui/src/components/modal.rs b/crates/ui/src/components/modal.rs index dec7a14a52..11611f9c0f 100644 --- a/crates/ui/src/components/modal.rs +++ b/crates/ui/src/components/modal.rs @@ -1,3 +1,5 @@ +#![allow(missing_docs)] + use crate::{ h_flex, v_flex, Clickable, Color, Headline, HeadlineSize, IconButton, IconButtonShape, IconName, Label, LabelCommon, LabelSize, Spacing, diff --git a/crates/ui/src/components/numeric_stepper.rs b/crates/ui/src/components/numeric_stepper.rs index 64ea79f21c..39be56a455 100644 --- a/crates/ui/src/components/numeric_stepper.rs +++ b/crates/ui/src/components/numeric_stepper.rs @@ -1,3 +1,5 @@ +#![allow(missing_docs)] + use gpui::ClickEvent; use crate::{prelude::*, IconButtonShape}; diff --git a/crates/ui/src/components/popover.rs b/crates/ui/src/components/popover.rs index af20f38186..5bd6c1ed7c 100644 --- a/crates/ui/src/components/popover.rs +++ b/crates/ui/src/components/popover.rs @@ -1,3 +1,5 @@ +#![allow(missing_docs)] + use crate::prelude::*; use crate::v_flex; use gpui::{ diff --git a/crates/ui/src/components/popover_menu.rs b/crates/ui/src/components/popover_menu.rs index 02604b2cc6..e05888bdf6 100644 --- a/crates/ui/src/components/popover_menu.rs +++ b/crates/ui/src/components/popover_menu.rs @@ -1,3 +1,5 @@ +#![allow(missing_docs)] + use std::{cell::RefCell, rc::Rc}; use gpui::{ diff --git a/crates/ui/src/components/radio.rs b/crates/ui/src/components/radio.rs index f3eeb9dac0..c4ceef5f83 100644 --- a/crates/ui/src/components/radio.rs +++ b/crates/ui/src/components/radio.rs @@ -1,3 +1,5 @@ +#![allow(missing_docs)] + use std::sync::Arc; use crate::prelude::*; diff --git a/crates/ui/src/components/right_click_menu.rs b/crates/ui/src/components/right_click_menu.rs index c340a4ad89..f68b85016c 100644 --- a/crates/ui/src/components/right_click_menu.rs +++ b/crates/ui/src/components/right_click_menu.rs @@ -1,3 +1,5 @@ +#![allow(missing_docs)] + use std::{cell::RefCell, rc::Rc}; use gpui::{ diff --git a/crates/ui/src/components/settings_container.rs b/crates/ui/src/components/settings_container.rs index df1c355e06..56248ce528 100644 --- a/crates/ui/src/components/settings_container.rs +++ b/crates/ui/src/components/settings_container.rs @@ -1,3 +1,5 @@ +#![allow(missing_docs)] + use gpui::AnyElement; use smallvec::SmallVec; diff --git a/crates/ui/src/components/settings_group.rs b/crates/ui/src/components/settings_group.rs index 6093964057..77b4416a4a 100644 --- a/crates/ui/src/components/settings_group.rs +++ b/crates/ui/src/components/settings_group.rs @@ -1,3 +1,5 @@ +#![allow(missing_docs)] + use gpui::AnyElement; use smallvec::SmallVec; diff --git a/crates/ui/src/components/stack.rs b/crates/ui/src/components/stack.rs index 74a5e80575..2af0a5d3f9 100644 --- a/crates/ui/src/components/stack.rs +++ b/crates/ui/src/components/stack.rs @@ -1,3 +1,5 @@ +#![allow(missing_docs)] + use gpui::{div, Div}; use crate::StyledExt; diff --git a/crates/ui/src/components/stories.rs b/crates/ui/src/components/stories.rs index 9014f5a470..88325f2201 100644 --- a/crates/ui/src/components/stories.rs +++ b/crates/ui/src/components/stories.rs @@ -1,3 +1,6 @@ +// We allow missing docs for stories as the docs will more or less be +// "This is the ___ story", which is not very useful. +#![allow(missing_docs)] mod avatar; mod button; mod checkbox; diff --git a/crates/ui/src/components/tab.rs b/crates/ui/src/components/tab.rs index 1ec4cd4aec..9540063c78 100644 --- a/crates/ui/src/components/tab.rs +++ b/crates/ui/src/components/tab.rs @@ -1,3 +1,4 @@ +#![allow(missing_docs)] use std::cmp::Ordering; use gpui::{AnyElement, IntoElement, Stateful}; diff --git a/crates/ui/src/components/tab_bar.rs b/crates/ui/src/components/tab_bar.rs index 0012c53ed8..5657721e17 100644 --- a/crates/ui/src/components/tab_bar.rs +++ b/crates/ui/src/components/tab_bar.rs @@ -1,3 +1,4 @@ +#![allow(missing_docs)] use gpui::{AnyElement, ScrollHandle}; use smallvec::SmallVec; diff --git a/crates/ui/src/components/tool_strip.rs b/crates/ui/src/components/tool_strip.rs index ced4b271ad..78767aadf7 100644 --- a/crates/ui/src/components/tool_strip.rs +++ b/crates/ui/src/components/tool_strip.rs @@ -1,3 +1,5 @@ +#![allow(missing_docs)] + use crate::prelude::*; use gpui::*; diff --git a/crates/ui/src/components/tooltip.rs b/crates/ui/src/components/tooltip.rs index dc02d60b36..89b89786b0 100644 --- a/crates/ui/src/components/tooltip.rs +++ b/crates/ui/src/components/tooltip.rs @@ -1,3 +1,5 @@ +#![allow(missing_docs)] + use gpui::{Action, AnyView, FocusHandle, IntoElement, Render, VisualContext}; use settings::Settings; use theme::ThemeSettings; diff --git a/crates/ui/src/key_bindings.rs b/crates/ui/src/key_bindings.rs deleted file mode 100644 index 7746d096fe..0000000000 --- a/crates/ui/src/key_bindings.rs +++ /dev/null @@ -1,170 +0,0 @@ -use gpui::{Action, FocusHandle, KeyBinding, Keystroke, WindowContext}; - -use crate::PlatformStyle; - -/// Returns a textual representation of the key binding for the given [`Action`]. -pub fn text_for_action(action: &dyn Action, cx: &mut WindowContext) -> Option { - let key_binding = cx.bindings_for_action(action).last().cloned()?; - Some(text_for_key_binding(key_binding, PlatformStyle::platform())) -} - -/// Returns a textual representation of the key binding for the given [`Action`] -/// as if the provided [`FocusHandle`] was focused. -pub fn text_for_action_in( - action: &dyn Action, - focus: &FocusHandle, - cx: &mut WindowContext, -) -> Option { - let key_binding = cx.bindings_for_action_in(action, focus).last().cloned()?; - Some(text_for_key_binding(key_binding, PlatformStyle::platform())) -} - -/// Returns a textual representation of the given key binding for the specified platform. -pub fn text_for_key_binding(key_binding: KeyBinding, platform_style: PlatformStyle) -> String { - key_binding - .keystrokes() - .iter() - .map(|keystroke| text_for_keystroke(keystroke, platform_style)) - .collect::>() - .join(" ") -} - -/// Returns a textual representation of the given [`Keystroke`]. -pub fn text_for_keystroke(keystroke: &Keystroke, platform_style: PlatformStyle) -> String { - let mut text = String::new(); - - let delimiter = match platform_style { - PlatformStyle::Mac => '-', - PlatformStyle::Linux | PlatformStyle::Windows => '+', - }; - - if keystroke.modifiers.function { - match platform_style { - PlatformStyle::Mac => text.push_str("fn"), - PlatformStyle::Linux | PlatformStyle::Windows => text.push_str("Fn"), - } - - text.push(delimiter); - } - - if keystroke.modifiers.control { - match platform_style { - PlatformStyle::Mac => text.push_str("Control"), - PlatformStyle::Linux | PlatformStyle::Windows => text.push_str("Ctrl"), - } - - text.push(delimiter); - } - - if keystroke.modifiers.alt { - match platform_style { - PlatformStyle::Mac => text.push_str("Option"), - PlatformStyle::Linux | PlatformStyle::Windows => text.push_str("Alt"), - } - - text.push(delimiter); - } - - if keystroke.modifiers.platform { - match platform_style { - PlatformStyle::Mac => text.push_str("Command"), - PlatformStyle::Linux => text.push_str("Super"), - PlatformStyle::Windows => text.push_str("Win"), - } - - text.push(delimiter); - } - - if keystroke.modifiers.shift { - match platform_style { - PlatformStyle::Mac | PlatformStyle::Linux | PlatformStyle::Windows => { - text.push_str("Shift") - } - } - - text.push(delimiter); - } - - fn capitalize(str: &str) -> String { - let mut chars = str.chars(); - match chars.next() { - None => String::new(), - Some(first_char) => first_char.to_uppercase().collect::() + chars.as_str(), - } - } - - let key = match keystroke.key.as_str() { - "pageup" => "PageUp", - "pagedown" => "PageDown", - key => &capitalize(key), - }; - - text.push_str(key); - - text -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_text_for_keystroke() { - assert_eq!( - text_for_keystroke(&Keystroke::parse("cmd-c").unwrap(), PlatformStyle::Mac), - "Command-C".to_string() - ); - assert_eq!( - text_for_keystroke(&Keystroke::parse("cmd-c").unwrap(), PlatformStyle::Linux), - "Super+C".to_string() - ); - assert_eq!( - text_for_keystroke(&Keystroke::parse("cmd-c").unwrap(), PlatformStyle::Windows), - "Win+C".to_string() - ); - - assert_eq!( - text_for_keystroke( - &Keystroke::parse("ctrl-alt-delete").unwrap(), - PlatformStyle::Mac - ), - "Control-Option-Delete".to_string() - ); - assert_eq!( - text_for_keystroke( - &Keystroke::parse("ctrl-alt-delete").unwrap(), - PlatformStyle::Linux - ), - "Ctrl+Alt+Delete".to_string() - ); - assert_eq!( - text_for_keystroke( - &Keystroke::parse("ctrl-alt-delete").unwrap(), - PlatformStyle::Windows - ), - "Ctrl+Alt+Delete".to_string() - ); - - assert_eq!( - text_for_keystroke( - &Keystroke::parse("shift-pageup").unwrap(), - PlatformStyle::Mac - ), - "Shift-PageUp".to_string() - ); - assert_eq!( - text_for_keystroke( - &Keystroke::parse("shift-pageup").unwrap(), - PlatformStyle::Linux - ), - "Shift+PageUp".to_string() - ); - assert_eq!( - text_for_keystroke( - &Keystroke::parse("shift-pageup").unwrap(), - PlatformStyle::Windows - ), - "Shift+PageUp".to_string() - ); - } -} diff --git a/crates/ui/src/prelude.rs b/crates/ui/src/prelude.rs index 895c755c78..d01ac11bc3 100644 --- a/crates/ui/src/prelude.rs +++ b/crates/ui/src/prelude.rs @@ -7,16 +7,17 @@ pub use gpui::{ WindowContext, }; -pub use crate::clickable::*; -pub use crate::disableable::*; -pub use crate::fixed::*; -pub use crate::selectable::*; pub use crate::styles::{rems_from_px, vh, vw, PlatformStyle, StyledTypography, TextSize}; -pub use crate::visible_on_hover::*; +pub use crate::traits::clickable::*; +pub use crate::traits::disableable::*; +pub use crate::traits::fixed::*; +pub use crate::traits::selectable::*; +pub use crate::traits::styled_ext::*; +pub use crate::traits::visible_on_hover::*; pub use crate::Spacing; pub use crate::{h_flex, v_flex}; pub use crate::{Button, ButtonSize, ButtonStyle, IconButton, SelectableButton}; -pub use crate::{ButtonCommon, Color, StyledExt}; +pub use crate::{ButtonCommon, Color}; pub use crate::{Headline, HeadlineSize}; pub use crate::{Icon, IconName, IconPosition, IconSize}; pub use crate::{Label, LabelCommon, LabelSize, LineHeightStyle}; diff --git a/crates/ui/src/styles/appearance.rs b/crates/ui/src/styles/appearance.rs index 57d4757a36..3b014b733c 100644 --- a/crates/ui/src/styles/appearance.rs +++ b/crates/ui/src/styles/appearance.rs @@ -1,14 +1,8 @@ use crate::prelude::*; use gpui::{WindowBackgroundAppearance, WindowContext}; -use theme::Appearance; - -/// Returns the current [Appearance]. -pub fn appearance(cx: &WindowContext) -> Appearance { - cx.theme().appearance -} /// Returns the [WindowBackgroundAppearance]. -pub fn window_appearance(cx: &WindowContext) -> WindowBackgroundAppearance { +fn window_appearance(cx: &WindowContext) -> WindowBackgroundAppearance { cx.theme().styles.window_background_appearance } diff --git a/crates/ui/src/styles/color.rs b/crates/ui/src/styles/color.rs index b35728e478..fe8de2ff73 100644 --- a/crates/ui/src/styles/color.rs +++ b/crates/ui/src/styles/color.rs @@ -5,28 +5,63 @@ use theme::ActiveTheme; #[derive(Debug, Default, PartialEq, Copy, Clone)] pub enum Color { #[default] + /// The default text color. Might be known as "foreground" or "primary" in + /// some theme systems. + /// + /// For less emphasis, consider using [`Color::Muted`] or [`Color::Hidden`]. Default, + /// A text color used for accents, such as links or highlights. Accent, - Created, - Deleted, - Disabled, - Error, - Hidden, - Hint, - Info, - Modified, + /// A color used to indicate a conflict, such as a version control merge conflict, or a conflict between a file in the editor and the file system. Conflict, - Ignored, - Muted, - Placeholder, - Player(u32), - Selected, - Success, - Warning, + /// A color used to indicate a newly created item, such as a new file in + /// version control, or a new file on disk. + Created, + /// It is highly, HIGHLY recommended not to use this! Using this color + /// means detaching it from any semantic meaning across themes. + /// + /// A custom color specified by an HSLA value. Custom(Hsla), + /// A color used to indicate a deleted item, such as a file removed from version control. + Deleted, + /// A color used for disabled UI elements or text, like a disabled button or menu item. + Disabled, + /// A color used to indicate an error condition, or something the user + /// cannot do. In very rare cases, it might be used to indicate dangerous or + /// destructive action. + Error, + /// A color used for elements that represent something that is hidden, like + /// a hidden file, or an element that should be visually de-emphasized. + Hidden, + /// A color used for hint or suggestion text, often a blue color. Use this + /// color to represent helpful, or semantically neutral information. + Hint, + /// A color used for items that are intentionally ignored, such as files ignored by version control. + Ignored, + /// A color used for informational messages or status indicators, often a blue color. + Info, + /// A color used to indicate a modified item, such as an edited file, or a modified entry in version control. + Modified, + /// A color used for text or UI elements that should be visually muted or de-emphasized. + /// + /// For more emphasis, consider using [`Color::Default`]. + /// + /// For less emphasis, consider using [`Color::Hidden`]. + Muted, + /// A color used for placeholder text in input fields. + Placeholder, + /// A color associated with a specific player number. + Player(u32), + /// A color used to indicate selected text or UI elements. + Selected, + /// A color used to indicate a successful operation or status. + Success, + /// A color used to indicate a warning condition. + Warning, } impl Color { + /// Returns the Color's HSLA value. pub fn color(&self, cx: &WindowContext) -> Hsla { match self { Color::Default => cx.theme().colors().text, diff --git a/crates/ui/src/styles/docs/elevation.md b/crates/ui/src/styles/docs/elevation.md deleted file mode 100644 index 677fd030fd..0000000000 --- a/crates/ui/src/styles/docs/elevation.md +++ /dev/null @@ -1,44 +0,0 @@ -# Elevation - -Elevation can be thought of as the physical closeness of an element to the user. Elements with lower elevations are physically further away from the user on the z-axis and appear to be underneath elements with higher elevations. - -Material Design 3 has a some great visualizations of elevation that may be helpful to understanding the mental modal of elevation. [Material Design – Elevation](https://m3.material.io/styles/elevation/overview) - -## Elevation Levels - -1. App Background (e.x.: Workspace, system window) -1. UI Surface (e.x.: Title Bar, Panel, Tab Bar) -1. Elevated Surface (e.x.: Palette, Notification, Floating Window) -1. Wash -1. Modal Surfaces (e.x.: Modal) -1. Dragged Element (This is a special case, see Layer section below) - -### App Background - -The app background constitutes the lowest elevation layer, appearing behind all other surfaces and components. It is predominantly used for the background color of the app. - -### Surface - -The Surface elevation level, located above the app background, is the standard level for all elements - -Example Elements: Title Bar, Panel, Tab Bar, Editor - -### Elevated Surface - -Non-Modal Elevated Surfaces appear above the UI surface layer and is used for things that should appear above most UI elements like an editor or panel, but not elements like popovers, context menus, modals, etc. - -Examples: Notifications, Palettes, Detached/Floating Windows, Detached/Floating Panels - -You could imagine a variant of the assistant that floats in a window above the editor on this elevation, or a floating terminal window that becomes less opaque when not focused. - -### Wash - -Wash denotes a distinct elevation reserved to isolate app UI layers from high elevation components such as modals, notifications, and overlaid panels. The wash may not consistently be visible when these components are active. This layer is often referred to as a scrim or overlay and the background color of the wash is typically deployed in its design. - -### Modal Surfaces - -Modal Surfaces are used for elements that should appear above all other UI elements and are located above the wash layer. This is the maximum elevation at which UI elements can be rendered - -Elements rendered at this layer have an enforced behavior: Any interaction outside of the modal will either dismiss the modal or prompt an action (Save your progress, etc) then dismiss the modal. - -If the element does not have this behavior, it should be rendered at the Elevated Surface layer. diff --git a/crates/ui/src/styles/elevation.rs b/crates/ui/src/styles/elevation.rs index c067802119..722111b46c 100644 --- a/crates/ui/src/styles/elevation.rs +++ b/crates/ui/src/styles/elevation.rs @@ -1,31 +1,32 @@ use gpui::{hsla, point, px, BoxShadow}; use smallvec::{smallvec, SmallVec}; -#[doc = include_str!("docs/elevation.md")] -#[derive(Debug, Clone, Copy, PartialEq, Eq)] -pub enum Elevation { - ElevationIndex(ElevationIndex), - LayerIndex(LayerIndex), - ElementIndex(ElementIndex), -} - -impl From for Elevation { - fn from(val: ElevationIndex) -> Self { - Elevation::ElevationIndex(val) - } -} - +/// Today, elevation is primarily used to add shadows to elements, and set the correct background for elements like buttons. +/// +/// Elevation can be thought of as the physical closeness of an element to the +/// user. Elements with lower elevations are physically further away on the +/// z-axis and appear to be underneath elements with higher elevations. +/// +/// In the future, a more complete approach to elevation may be added. #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub enum ElevationIndex { + /// On the layer of the app background. This is under panels, panes, and + /// other surfaces. Background, + /// The primary surface – Contains panels, panes, containers, etc. Surface, + /// A surface that is elevated above the primary surface. but below washes, models, and dragged elements. ElevatedSurface, + /// A surface that is above all non-modal surfaces, and separates the app from focused intents, like dialogs, alerts, modals, etc. Wash, + /// A surface above the [ElevationIndex::Wash] that is used for dialogs, alerts, modals, etc. ModalSurface, + /// A surface above all other surfaces, reserved exclusively for dragged elements, like a dragged file, tab or other draggable element. DraggedElement, } impl ElevationIndex { + /// Returns an appropriate shadow for the given elevation index. pub fn shadow(self) -> SmallVec<[BoxShadow; 2]> { match self { ElevationIndex::Surface => smallvec![], @@ -62,21 +63,3 @@ impl ElevationIndex { } } } - -#[derive(Debug, Clone, Copy, PartialEq, Eq)] -pub enum LayerIndex { - BehindElement, - Element, - ElevatedElement, -} - -/// An appropriate z-index for the given layer based on its intended usage. -#[derive(Debug, Clone, Copy, PartialEq, Eq)] -pub enum ElementIndex { - Effect, - Background, - Tint, - Highlight, - Content, - Overlay, -} diff --git a/crates/ui/src/styles/spacing.rs b/crates/ui/src/styles/spacing.rs index 282980fcaf..a2089d9586 100644 --- a/crates/ui/src/styles/spacing.rs +++ b/crates/ui/src/styles/spacing.rs @@ -4,6 +4,11 @@ use theme::{ThemeSettings, UiDensity}; use crate::{rems_from_px, BASE_REM_SIZE_IN_PX}; +/// A dynamic spacing system that adjusts spacing based on +/// [UiDensity]. +/// +/// When possible, [Spacing] should be used over manual +/// or built-in spacing values in places dynamic spacing is needed. #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] pub enum Spacing { /// No spacing @@ -38,6 +43,7 @@ pub enum Spacing { } impl Spacing { + /// Returns the spacing's scaling ratio in pixels. pub fn spacing_ratio(self, cx: &WindowContext) -> f32 { match ThemeSettings::get_global(cx).ui_density { UiDensity::Compact => match self { @@ -73,10 +79,12 @@ impl Spacing { } } + /// Returns the spacing's value in rems. pub fn rems(self, cx: &WindowContext) -> Rems { rems(self.spacing_ratio(cx)) } + /// Returns the spacing's value in pixels. pub fn px(self, cx: &WindowContext) -> Pixels { let ui_font_size_f32: f32 = ThemeSettings::get_global(cx).ui_font_size.into(); @@ -84,10 +92,14 @@ impl Spacing { } } -pub fn user_spacing_style(cx: &WindowContext) -> UiDensity { +fn user_spacing_style(cx: &WindowContext) -> UiDensity { ThemeSettings::get_global(cx).ui_density } +/// Returns a custom spacing value based on the current [`UiDensity`]. +/// +/// If you use this, talk to @iamnbutler and let me know what you're doing +/// that needs custom spacing– I'd love to understand so we can extend the system further and remove the need for this. pub fn custom_spacing(cx: &WindowContext, size: f32) -> Rems { rems_from_px(size * user_spacing_style(cx).spacing_ratio()) } diff --git a/crates/ui/src/styles/typography.rs b/crates/ui/src/styles/typography.rs index 4afd3b9303..ef9c946ed5 100644 --- a/crates/ui/src/styles/typography.rs +++ b/crates/ui/src/styles/typography.rs @@ -87,6 +87,7 @@ pub trait StyledTypography: Styled + Sized { impl StyledTypography for E {} +/// A utility for getting the size of various semantic text sizes. #[derive(Debug, Default, Clone)] pub enum TextSize { /// The default size for UI text. @@ -128,6 +129,7 @@ pub enum TextSize { } impl TextSize { + /// Returns the text size in rems. pub fn rems(self, cx: &WindowContext) -> Rems { let theme_settings = ThemeSettings::get_global(cx); @@ -143,20 +145,27 @@ impl TextSize { } /// The size of a [`Headline`] element +/// +/// Defaults to a Major Second scale. #[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Copy, Default)] pub enum HeadlineSize { + /// An extra small headline - `~14px` @16px/rem XSmall, + /// A small headline - `16px` @16px/rem Small, #[default] + /// A medium headline - `~18px` @16px/rem Medium, + /// A large headline - `~20px` @16px/rem Large, + /// An extra large headline - `~22px` @16px/rem XLarge, } impl HeadlineSize { - pub fn size(self) -> Rems { + /// Returns the headline size in rems. + pub fn rems(self) -> Rems { match self { - // Based on the Major Second scale Self::XSmall => rems(0.88), Self::Small => rems(1.0), Self::Medium => rems(1.125), @@ -165,6 +174,7 @@ impl HeadlineSize { } } + /// Returns the line height for the headline size. pub fn line_height(self) -> Rems { match self { Self::XSmall => rems(1.6), @@ -176,6 +186,8 @@ impl HeadlineSize { } } +/// A headline element, used to emphasize some text and +/// create a visual hierarchy. #[derive(IntoElement)] pub struct Headline { size: HeadlineSize, @@ -190,13 +202,14 @@ impl RenderOnce for Headline { div() .font(ui_font) .line_height(self.size.line_height()) - .text_size(self.size.size()) + .text_size(self.size.rems()) .text_color(cx.theme().colors().text) .child(self.text) } } impl Headline { + /// Create a new headline element. pub fn new(text: impl Into) -> Self { Self { size: HeadlineSize::default(), @@ -205,11 +218,13 @@ impl Headline { } } + /// Set the size of the headline. pub fn size(mut self, size: HeadlineSize) -> Self { self.size = size; self } + /// Set the color of the headline. pub fn color(mut self, color: Color) -> Self { self.color = color; self diff --git a/crates/ui/src/tests.rs b/crates/ui/src/tests.rs new file mode 100644 index 0000000000..3f26326a05 --- /dev/null +++ b/crates/ui/src/tests.rs @@ -0,0 +1 @@ +mod path_str; diff --git a/crates/ui/src/path_str.rs b/crates/ui/src/tests/path_str.rs similarity index 54% rename from crates/ui/src/path_str.rs rename to crates/ui/src/tests/path_str.rs index 2ebb3fedb3..6c1545ec71 100644 --- a/crates/ui/src/path_str.rs +++ b/crates/ui/src/tests/path_str.rs @@ -1,3 +1,5 @@ +// We need to test [ui_macros::DerivePathStr] here as we can't invoke it +// in the `ui_macros` crate. #[cfg(test)] mod tests { use strum::EnumString; @@ -8,26 +10,26 @@ mod tests { #[derive(Debug, EnumString, DerivePathStr)] #[strum(serialize_all = "snake_case")] #[path_str(prefix = "test_prefix")] - enum MyEnum { + enum SomeAsset { FooBar, Baz, } - assert_eq!(MyEnum::FooBar.path(), "test_prefix/foo_bar"); - assert_eq!(MyEnum::Baz.path(), "test_prefix/baz"); + assert_eq!(SomeAsset::FooBar.path(), "test_prefix/foo_bar"); + assert_eq!(SomeAsset::Baz.path(), "test_prefix/baz"); } #[test] fn test_derive_path_str_with_prefix_and_suffix() { #[derive(Debug, EnumString, DerivePathStr)] #[strum(serialize_all = "snake_case")] - #[path_str(prefix = "test_prefix", suffix = ".txt")] - enum MyEnum { + #[path_str(prefix = "test_prefix", suffix = ".svg")] + enum SomeAsset { FooBar, Baz, } - assert_eq!(MyEnum::FooBar.path(), "test_prefix/foo_bar.txt"); - assert_eq!(MyEnum::Baz.path(), "test_prefix/baz.txt"); + assert_eq!(SomeAsset::FooBar.path(), "test_prefix/foo_bar.svg"); + assert_eq!(SomeAsset::Baz.path(), "test_prefix/baz.svg"); } } diff --git a/crates/ui/src/traits.rs b/crates/ui/src/traits.rs new file mode 100644 index 0000000000..7e52f2a867 --- /dev/null +++ b/crates/ui/src/traits.rs @@ -0,0 +1,6 @@ +pub mod clickable; +pub mod disableable; +pub mod fixed; +pub mod selectable; +pub mod styled_ext; +pub mod visible_on_hover; diff --git a/crates/ui/src/clickable.rs b/crates/ui/src/traits/clickable.rs similarity index 100% rename from crates/ui/src/clickable.rs rename to crates/ui/src/traits/clickable.rs diff --git a/crates/ui/src/disableable.rs b/crates/ui/src/traits/disableable.rs similarity index 100% rename from crates/ui/src/disableable.rs rename to crates/ui/src/traits/disableable.rs diff --git a/crates/ui/src/fixed.rs b/crates/ui/src/traits/fixed.rs similarity index 100% rename from crates/ui/src/fixed.rs rename to crates/ui/src/traits/fixed.rs diff --git a/crates/ui/src/selectable.rs b/crates/ui/src/traits/selectable.rs similarity index 100% rename from crates/ui/src/selectable.rs rename to crates/ui/src/traits/selectable.rs diff --git a/crates/ui/src/styled_ext.rs b/crates/ui/src/traits/styled_ext.rs similarity index 100% rename from crates/ui/src/styled_ext.rs rename to crates/ui/src/traits/styled_ext.rs diff --git a/crates/ui/src/visible_on_hover.rs b/crates/ui/src/traits/visible_on_hover.rs similarity index 85% rename from crates/ui/src/visible_on_hover.rs rename to crates/ui/src/traits/visible_on_hover.rs index aefa7ac10c..fc0bb837d7 100644 --- a/crates/ui/src/visible_on_hover.rs +++ b/crates/ui/src/traits/visible_on_hover.rs @@ -1,5 +1,7 @@ use gpui::{InteractiveElement, SharedString, Styled}; +/// A trait for elements that can be made visible on hover by +/// tracking a specific group. pub trait VisibleOnHover { /// Sets the element to only be visible when the specified group is hovered. /// diff --git a/crates/ui/src/ui.rs b/crates/ui/src/ui.rs index 4f5d6314be..101de4f3ef 100644 --- a/crates/ui/src/ui.rs +++ b/crates/ui/src/ui.rs @@ -1,28 +1,22 @@ +#![deny(missing_docs)] + //! # UI – Zed UI Primitives & Components //! //! This crate provides a set of UI primitives and components that are used to build all of the elements in Zed's UI. //! +//! ## Related Crates: +//! +//! - [`ui_macros`] - proc_macros support for this crate +//! - [`ui_input`] - the single line input component +//! -mod clickable; mod components; -mod disableable; -mod fixed; -mod key_bindings; -mod path_str; pub mod prelude; -mod selectable; -mod styled_ext; mod styles; +mod tests; +mod traits; pub mod utils; -mod visible_on_hover; -mod with_rem_size; -pub use clickable::*; pub use components::*; -pub use disableable::*; -pub use fixed::*; -pub use key_bindings::*; pub use prelude::*; -pub use styled_ext::*; pub use styles::*; -pub use with_rem_size::*; diff --git a/crates/ui/src/utils.rs b/crates/ui/src/utils.rs index ed1fec690f..b68d6e6bbd 100644 --- a/crates/ui/src/utils.rs +++ b/crates/ui/src/utils.rs @@ -1,5 +1,7 @@ -//! UI-related utilities (e.g. converting dates to a human-readable form). +//! UI-related utilities mod format_distance; +mod with_rem_size; pub use format_distance::*; +pub use with_rem_size::*; diff --git a/crates/ui/src/utils/format_distance.rs b/crates/ui/src/utils/format_distance.rs index 2abcee6684..af4f0d9505 100644 --- a/crates/ui/src/utils/format_distance.rs +++ b/crates/ui/src/utils/format_distance.rs @@ -1,3 +1,6 @@ +// This won't be documented further as it is intended to be removed, or merged with the `time_format` crate. +#![allow(missing_docs)] + use chrono::{DateTime, Local, NaiveDateTime}; #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] diff --git a/crates/ui/src/with_rem_size.rs b/crates/ui/src/utils/with_rem_size.rs similarity index 95% rename from crates/ui/src/with_rem_size.rs rename to crates/ui/src/utils/with_rem_size.rs index f286177efb..9011d1e28e 100644 --- a/crates/ui/src/with_rem_size.rs +++ b/crates/ui/src/utils/with_rem_size.rs @@ -10,6 +10,8 @@ pub struct WithRemSize { } impl WithRemSize { + /// Create a new [WithRemSize] element, which sets a + /// particular rem size for its children. pub fn new(rem_size: impl Into) -> Self { Self { div: div(),