Add Headline component

Nate Butler created

Change summary

crates/ui/src/components.rs            |  2 
crates/ui/src/components/typography.rs | 71 ++++++++++++++++++++++++++++
crates/ui/src/prelude.rs               |  1 
3 files changed, 74 insertions(+)

Detailed changes

crates/ui/src/components.rs 🔗

@@ -16,6 +16,7 @@ mod stack;
 mod tab;
 mod tab_bar;
 mod tooltip;
+mod typography;
 
 #[cfg(feature = "stories")]
 mod stories;
@@ -38,6 +39,7 @@ pub use stack::*;
 pub use tab::*;
 pub use tab_bar::*;
 pub use tooltip::*;
+pub use typography::*;
 
 #[cfg(feature = "stories")]
 pub use stories::*;

crates/ui/src/components/typography.rs 🔗

@@ -0,0 +1,71 @@
+use gpui::{
+    div, rems, IntoElement, ParentElement, Rems, RenderOnce, SharedString, Styled, WindowContext,
+};
+use settings::Settings;
+use theme::{ActiveTheme, ThemeSettings};
+
+#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Copy, Default)]
+pub enum HeadlineSize {
+    XSmall,
+    Small,
+    #[default]
+    Medium,
+    Large,
+    XLarge,
+}
+
+impl HeadlineSize {
+    pub fn size(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),
+            Self::Large => rems(1.27),
+            Self::XLarge => rems(1.43),
+        }
+    }
+
+    pub fn line_height(self) -> Rems {
+        match self {
+            Self::XSmall => rems(1.6),
+            Self::Small => rems(1.6),
+            Self::Medium => rems(1.6),
+            Self::Large => rems(1.6),
+            Self::XLarge => rems(1.6),
+        }
+    }
+}
+
+#[derive(IntoElement)]
+pub struct Headline {
+    size: HeadlineSize,
+    text: SharedString,
+}
+
+impl RenderOnce for Headline {
+    fn render(self, cx: &mut WindowContext) -> impl IntoElement {
+        let ui_font = ThemeSettings::get_global(cx).ui_font.family.clone();
+
+        div()
+            .font(ui_font)
+            .line_height(self.size.line_height())
+            .text_size(self.size.size())
+            .text_color(cx.theme().colors().text)
+            .child(self.text)
+    }
+}
+
+impl Headline {
+    pub fn new(text: impl Into<SharedString>) -> Self {
+        Self {
+            size: HeadlineSize::default(),
+            text: text.into(),
+        }
+    }
+
+    pub fn size(mut self, size: HeadlineSize) -> Self {
+        self.size = size;
+        self
+    }
+}

crates/ui/src/prelude.rs 🔗

@@ -14,6 +14,7 @@ pub use crate::visible_on_hover::*;
 pub use crate::{h_stack, v_stack};
 pub use crate::{Button, ButtonSize, ButtonStyle, IconButton};
 pub use crate::{ButtonCommon, Color, StyledExt};
+pub use crate::{Headline, HeadlineSize};
 pub use crate::{Icon, IconElement, IconPosition, IconSize};
 pub use crate::{Label, LabelCommon, LabelSize, LineHeightStyle};
 pub use theme::ActiveTheme;