use crate::prelude::*;use gpui::{ div, rems, AnyElement, App, IntoElement, ParentElement, Rems, RenderOnce, SharedString, Styled, Window,};use settings::Settings;use theme::{ActiveTheme, ThemeSettings}; use crate::{rems_from_px, Color}; /// Extends [`gpui::Styled`] with typography-related styling methods.pub trait StyledTypography: Styled + Sized { /// Sets the font family to the buffer font. fn font_buffer(self, cx: &App) -> Self { let settings = ThemeSettings::get_global(cx); let buffer_font_family = settings.buffer_font.family.clone(); self.font_family(buffer_font_family) } /// Sets the font family to the UI font. fn font_ui(self, cx: &App) -> Self { let settings = ThemeSettings::get_global(cx); let ui_font_family = settings.ui_font.family.clone(); self.font_family(ui_font_family) } /// Sets the text size using a [`TextSize`]. fn text_ui_size(self, size: TextSize, cx: &App) -> Self { self.text_size(size.rems(cx)) } /// The large size for UI text. /// /// `1rem` or `16px` at the default scale of `1rem` = `16px`. /// /// Note: The absolute size of this text will change based on a user's `ui_scale` setting. /// /// Use `text_ui` for regular-sized text. fn text_ui_lg(self, cx: &App) -> Self { self.text_size(TextSize::Large.rems(cx)) } /// The default size for UI text. /// /// `0.825rem` or `14px` at the default scale of `1rem` = `16px`. /// /// Note: The absolute size of this text will change based on a user's `ui_scale` setting. /// /// Use `text_ui_sm` for smaller text. fn text_ui(self, cx: &App) -> Self { self.text_size(TextSize::default().rems(cx)) } /// The small size for UI text. /// /// `0.75rem` or `12px` at the default scale of `1rem` = `16px`. /// /// Note: The absolute size of this text will change based on a user's `ui_scale` setting. /// /// Use `text_ui` for regular-sized text. fn text_ui_sm(self, cx: &App) -> Self { self.text_size(TextSize::Small.rems(cx)) } /// The extra small size for UI text. /// /// `0.625rem` or `10px` at the default scale of `1rem` = `16px`. /// /// Note: The absolute size of this text will change based on a user's `ui_scale` setting. /// /// Use `text_ui` for regular-sized text. fn text_ui_xs(self, cx: &App) -> Self { self.text_size(TextSize::XSmall.rems(cx)) } /// The font size for buffer text. /// /// Retrieves the default font size, or the user's custom font size if set. /// /// This should only be used for text that is displayed in a buffer, /// or other places that text needs to match the user's buffer font size. fn text_buffer(self, cx: &App) -> Self { let settings = ThemeSettings::get_global(cx); self.text_size(settings.buffer_font_size(cx)) }} impl<E: Styled> 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. /// /// `0.825rem` or `14px` at the default scale of `1rem` = `16px`. /// /// Note: The absolute size of this text will change based on a user's `ui_scale` setting. #[default] Default, /// The large size for UI text. /// /// `1rem` or `16px` at the default scale of `1rem` = `16px`. /// /// Note: The absolute size of this text will change based on a user's `ui_scale` setting. Large, /// The small size for UI text. /// /// `0.75rem` or `12px` at the default scale of `1rem` = `16px`. /// /// Note: The absolute size of this text will change based on a user's `ui_scale` setting. Small, /// The extra small size for UI text. /// /// `0.625rem` or `10px` at the default scale of `1rem` = `16px`. /// /// Note: The absolute size of this text will change based on a user's `ui_scale` setting. XSmall, /// The `ui_font_size` set by the user. Ui, /// The `buffer_font_size` set by the user. Editor, // TODO: The terminal settings will need to be passed to // ThemeSettings before we can enable this. //// The `terminal.font_size` set by the user. // Terminal,} impl TextSize { /// Returns the text size in rems. pub fn rems(self, cx: &App) -> Rems { let theme_settings = ThemeSettings::get_global(cx); match self { Self::Large => rems_from_px(16.), Self::Default => rems_from_px(14.), Self::Small => rems_from_px(12.), Self::XSmall => rems_from_px(10.), Self::Ui => rems_from_px(theme_settings.ui_font_size(cx).into()), Self::Editor => rems_from_px(theme_settings.buffer_font_size(cx).into()), } }} /// 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 { /// Returns the headline size in rems. pub fn rems(self) -> Rems { match self { 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), } } /// Returns the line height for the headline size. 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), } }} /// A headline element, used to emphasize some text and/// create a visual hierarchy.#[derive(IntoElement, IntoComponent)]pub struct Headline { size: HeadlineSize, text: SharedString, color: Color,} impl RenderOnce for Headline { fn render(self, _window: &mut Window, cx: &mut App) -> impl IntoElement { let ui_font = ThemeSettings::get_global(cx).ui_font.clone(); div() .font(ui_font) .line_height(self.size.line_height()) .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<SharedString>) -> Self { Self { size: HeadlineSize::default(), text: text.into(), color: Color::default(), } } /// 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 }} // View this component preview using `workspace: open component-preview`impl ComponentPreview for Headline { fn preview(_window: &mut Window, _cx: &mut App) -> AnyElement { v_flex() .gap_1() .children(vec![ single_example( "XLarge", Headline::new("XLarge Headline") .size(HeadlineSize::XLarge) .into_any_element(), ), single_example( "Large", Headline::new("Large Headline") .size(HeadlineSize::Large) .into_any_element(), ), single_example( "Medium (Default)", Headline::new("Medium Headline").into_any_element(), ), single_example( "Small", Headline::new("Small Headline") .size(HeadlineSize::Small) .into_any_element(), ), single_example( "XSmall", Headline::new("XSmall Headline") .size(HeadlineSize::XSmall) .into_any_element(), ), ]) .into_any_element() }}
use crate::prelude::*;
use gpui::{
div, rems, AnyElement, App, IntoElement, ParentElement, Rems, RenderOnce, SharedString, Styled,
Window,
};
use settings::Settings;
use theme::{ActiveTheme, ThemeSettings};
use crate::{rems_from_px, Color};
/// Extends [`gpui::Styled`] with typography-related styling methods.
pub trait StyledTypography: Styled + Sized {
/// Sets the font family to the buffer font.
fn font_buffer(self, cx: &App) -> Self {
let settings = ThemeSettings::get_global(cx);
let buffer_font_family = settings.buffer_font.family.clone();
self.font_family(buffer_font_family)
}
/// Sets the font family to the UI font.
fn font_ui(self, cx: &App) -> Self {
let settings = ThemeSettings::get_global(cx);
let ui_font_family = settings.ui_font.family.clone();
self.font_family(ui_font_family)
}
/// Sets the text size using a [`TextSize`].
fn text_ui_size(self, size: TextSize, cx: &App) -> Self {
self.text_size(size.rems(cx))
}
/// The large size for UI text.
///
/// `1rem` or `16px` at the default scale of `1rem` = `16px`.
///
/// Note: The absolute size of this text will change based on a user's `ui_scale` setting.
///
/// Use `text_ui` for regular-sized text.
fn text_ui_lg(self, cx: &App) -> Self {
self.text_size(TextSize::Large.rems(cx))
}
/// The default size for UI text.
///
/// `0.825rem` or `14px` at the default scale of `1rem` = `16px`.
///
/// Note: The absolute size of this text will change based on a user's `ui_scale` setting.
///
/// Use `text_ui_sm` for smaller text.
fn text_ui(self, cx: &App) -> Self {
self.text_size(TextSize::default().rems(cx))
}
/// The small size for UI text.
///
/// `0.75rem` or `12px` at the default scale of `1rem` = `16px`.
///
/// Note: The absolute size of this text will change based on a user's `ui_scale` setting.
///
/// Use `text_ui` for regular-sized text.
fn text_ui_sm(self, cx: &App) -> Self {
self.text_size(TextSize::Small.rems(cx))
}
/// The extra small size for UI text.
///
/// `0.625rem` or `10px` at the default scale of `1rem` = `16px`.
///
/// Note: The absolute size of this text will change based on a user's `ui_scale` setting.
///
/// Use `text_ui` for regular-sized text.
fn text_ui_xs(self, cx: &App) -> Self {
self.text_size(TextSize::XSmall.rems(cx))
}
/// The font size for buffer text.
///
/// Retrieves the default font size, or the user's custom font size if set.
///
/// This should only be used for text that is displayed in a buffer,
/// or other places that text needs to match the user's buffer font size.
fn text_buffer(self, cx: &App) -> Self {
let settings = ThemeSettings::get_global(cx);
self.text_size(settings.buffer_font_size(cx))
}
}
impl<E: Styled> 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.
///
/// `0.825rem` or `14px` at the default scale of `1rem` = `16px`.
///
/// Note: The absolute size of this text will change based on a user's `ui_scale` setting.
#[default]
Default,
/// The large size for UI text.
///
/// `1rem` or `16px` at the default scale of `1rem` = `16px`.
///
/// Note: The absolute size of this text will change based on a user's `ui_scale` setting.
Large,
/// The small size for UI text.
///
/// `0.75rem` or `12px` at the default scale of `1rem` = `16px`.
///
/// Note: The absolute size of this text will change based on a user's `ui_scale` setting.
Small,
/// The extra small size for UI text.
///
/// `0.625rem` or `10px` at the default scale of `1rem` = `16px`.
///
/// Note: The absolute size of this text will change based on a user's `ui_scale` setting.
XSmall,
/// The `ui_font_size` set by the user.
Ui,
/// The `buffer_font_size` set by the user.
Editor,
// TODO: The terminal settings will need to be passed to
// ThemeSettings before we can enable this.
//// The `terminal.font_size` set by the user.
// Terminal,
}
impl TextSize {
/// Returns the text size in rems.
pub fn rems(self, cx: &App) -> Rems {
let theme_settings = ThemeSettings::get_global(cx);
match self {
Self::Large => rems_from_px(16.),
Self::Default => rems_from_px(14.),
Self::Small => rems_from_px(12.),
Self::XSmall => rems_from_px(10.),
Self::Ui => rems_from_px(theme_settings.ui_font_size(cx).into()),
Self::Editor => rems_from_px(theme_settings.buffer_font_size(cx).into()),
}
}
}
/// 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 {
/// Returns the headline size in rems.
pub fn rems(self) -> Rems {
match self {
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),
}
}
/// Returns the line height for the headline size.
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),
}
}
}
/// A headline element, used to emphasize some text and
/// create a visual hierarchy.
#[derive(IntoElement, IntoComponent)]
pub struct Headline {
size: HeadlineSize,
text: SharedString,
color: Color,
}
impl RenderOnce for Headline {
fn render(self, _window: &mut Window, cx: &mut App) -> impl IntoElement {
let ui_font = ThemeSettings::get_global(cx).ui_font.clone();
div()
.font(ui_font)
.line_height(self.size.line_height())
.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<SharedString>) -> Self {
Self {
size: HeadlineSize::default(),
text: text.into(),
color: Color::default(),
}
}
/// 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
}
}
// View this component preview using `workspace: open component-preview`
impl ComponentPreview for Headline {
fn preview(_window: &mut Window, _cx: &mut App) -> AnyElement {
v_flex()
.gap_1()
.children(vec![
single_example(
"XLarge",
Headline::new("XLarge Headline")
.size(HeadlineSize::XLarge)
.into_any_element(),
),
single_example(
"Large",
Headline::new("Large Headline")
.size(HeadlineSize::Large)
.into_any_element(),
),
single_example(
"Medium (Default)",
Headline::new("Medium Headline").into_any_element(),
),
single_example(
"Small",
Headline::new("Small Headline")
.size(HeadlineSize::Small)
.into_any_element(),
),
single_example(
"XSmall",
Headline::new("XSmall Headline")
.size(HeadlineSize::XSmall)
.into_any_element(),
),
])
.into_any_element()
}
}