theme: Use font_family for all elements. (#1618)

Close #1613

- And add `mono_font_family` and `mono_font_size` for code editor.
This commit is contained in:
Jason Lee 2025-11-17 11:18:17 +08:00 committed by GitHub
parent 0a5c799aba
commit 6c4de54fa4
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
13 changed files with 76 additions and 30 deletions

View file

@ -23,27 +23,38 @@
"description": "The base font size, default is 16.",
"type": ["number", "null"],
"format": "float",
"default": null
"default": 16
},
"font.family": {
"description": "The base font family, default is system font: `.SystemUIFont`.",
"type": ["string", "null"],
"default": ".SystemUIFont"
},
"mono_font.size": {
"description": "The base monospace font size, default is 13.",
"type": ["number", "null"],
"format": "float",
"default": 13
},
"mono_font.family": {
"description": "The monospace font family, default is platform specific:\nmacOS: `Menlo`\n- Windows: `Consolas`\n- Linux: `DejaVu Sans Mono`",
"type": ["string", "null"],
"default": null
},
"radius": {
"description": "The border radius for general elements, default is 6.",
"type": ["number", "null"],
"default": null
"default": 6
},
"radius.lg": {
"description": "The border radius for large elements like Dialogs and Notifications, default is 8.",
"type": ["number", "null"],
"default": null
"default": 8
},
"shadow": {
"description": "Set shadows in the theme, for example the Input and Button, default is true.",
"type": ["boolean", "null"],
"default": null
"default": true
},
"themes": {
"type": "array",

View file

@ -1003,8 +1003,8 @@ impl Render for Example {
.bordered(false)
.p_0()
.h_full()
.font_family("Monaco")
.text_size(px(12.))
.font_family(cx.theme().mono_font_family.clone())
.text_size(cx.theme().mono_font_size)
.focus_bordered(false)
.into_any_element(),
),

View file

@ -1,5 +1,6 @@
use gpui::*;
use gpui_component::{
ActiveTheme as _,
highlighter::Language,
input::{Input, InputState, TabSize},
resizable::h_resizable,
@ -52,8 +53,8 @@ impl Render for Example {
div()
.id("source")
.size_full()
.font_family("Menlo")
.text_size(px(13.))
.font_family(cx.theme().mono_font_family.clone())
.text_size(cx.theme().mono_font_size)
.child(
Input::new(&self.input_state)
.h_full()

View file

@ -1,5 +1,6 @@
use gpui::*;
use gpui_component::{
ActiveTheme as _,
highlighter::Language,
input::{Input, InputEvent, InputState, TabSize},
resizable::{h_resizable, resizable_panel},
@ -83,8 +84,8 @@ impl Render for Example {
div()
.id("source")
.size_full()
.font_family("Monaco")
.text_size(px(12.))
.font_family(cx.theme().mono_font_family.clone())
.text_size(cx.theme().mono_font_size)
.child(
Input::new(&self.input_state)
.h_full()

View file

@ -416,7 +416,7 @@ impl Render for StoryTiles {
let notification_layer = Root::render_notification_layer(window, cx);
div()
.font_family(".SystemUIFont")
.font_family(cx.theme().font_family.clone())
.relative()
.size_full()
.flex()

View file

@ -8,6 +8,7 @@ use rust_i18n::t;
use crate::{
input::{self, popovers::ContextMenu, InputState},
menu::PopupMenu,
ActiveTheme as _,
};
/// Context menu for mouse right clicks.
@ -125,7 +126,7 @@ impl MouseContextMenu {
}
impl Render for MouseContextMenu {
fn render(&mut self, _: &mut Window, _: &mut Context<Self>) -> impl IntoElement {
fn render(&mut self, _: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
if !self.open {
return div().into_any_element();
}
@ -137,8 +138,7 @@ impl Render for MouseContextMenu {
.position(self.mouse_position)
.child(
div()
.font_family(".SystemUIFont")
.text_size(px(14.))
.font_family(cx.theme().font_family.clone())
.cursor_default()
.child(self.menu.clone()),
),

View file

@ -414,7 +414,7 @@ impl Render for SearchPanel {
.on_action(cx.listener(Self::on_action_next))
.on_action(cx.listener(Self::on_action_escape))
.on_action(cx.listener(Self::on_action_tab))
.font_family(".SystemUIFont")
.font_family(cx.theme().font_family.clone())
.items_center()
.py_2()
.px_3()

View file

@ -434,8 +434,8 @@ impl Render for DivInspector {
v_flex()
.flex_1()
.gap_y_1()
.font_family("Monaco")
.text_size(px(12.))
.font_family(cx.theme().mono_font_family.clone())
.text_size(cx.theme().mono_font_size)
.child(Input::new(&self.rust_state.state).h_full())
.when_some(self.rust_state.error.clone(), |this, err| {
this.child(Alert::error("rust-error", err).text_xs())
@ -462,8 +462,8 @@ impl Render for DivInspector {
v_flex()
.flex_1()
.gap_y_1()
.font_family("Monaco")
.text_size(px(12.))
.font_family(cx.theme().mono_font_family.clone())
.text_size(cx.theme().mono_font_size)
.child(Input::new(&self.json_state.state).h_full())
.when_some(self.json_state.error.clone(), |this, err| {
this.child(Alert::error("json-error", err).text_xs())
@ -487,7 +487,7 @@ fn render_inspector(
v_flex()
.id("inspector")
.font_family(".SystemUIFont")
.font_family(cx.theme().font_family.clone())
.size_full()
.bg(cx.theme().background)
.border_l_1()

View file

@ -388,8 +388,7 @@ impl Root {
impl Render for Root {
fn render(&mut self, window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
let base_font_size = cx.theme().font_size;
window.set_rem_size(base_font_size);
window.set_rem_size(cx.theme().font_size);
window_border().child(
div()
@ -399,7 +398,7 @@ impl Render for Root {
.on_action(cx.listener(Self::on_action_tab_prev))
.relative()
.size_full()
.font_family(".SystemUIFont")
.font_family(cx.theme().font_family.clone())
.bg(cx.theme().background)
.text_color(cx.theme().foreground)
.child(self.view.clone()),

View file

@ -371,8 +371,8 @@ impl CodeBlock {
.p_3()
.rounded(cx.theme().radius)
.bg(cx.theme().secondary.opacity(0.85))
.font_family("Menlo, Monaco, Consolas, monospace")
.text_size(rems(0.875))
.font_family(cx.theme().mono_font_family.clone())
.text_size(cx.theme().mono_font_size)
.relative()
.refine_style(&style.code_block)
.child(Inline::new(

View file

@ -45,8 +45,20 @@ pub struct Theme {
pub dark_theme: Rc<ThemeConfig>,
pub mode: ThemeMode,
/// The font family for the application, default is `.SystemUIFont`.
pub font_family: SharedString,
/// The base font size for the application, default is 16px.
pub font_size: Pixels,
/// The monospace font family for the application.
///
/// Defaults to:
///
/// - macOS: `Menlo`
/// - Windows: `Consolas`
/// - Linux: `DejaVu Sans Mono`
pub mono_font_family: SharedString,
/// The monospace font size for the application, default is 13px.
pub mono_font_size: Pixels,
/// Radius for the general elements.
pub radius: Pixels,
/// Radius for the large elements, e.g.: Dialog, Notification border radius.
@ -172,14 +184,17 @@ impl From<&ThemeColor> for Theme {
Theme {
mode: ThemeMode::default(),
transparent: Hsla::transparent_black(),
font_family: ".SystemUIFont".into(),
font_size: px(16.),
font_family: if cfg!(target_os = "macos") {
".SystemUIFont".into()
mono_font_family: if cfg!(target_os = "macos") {
// https://en.wikipedia.org/wiki/Menlo_(typeface)
"Menlo".into()
} else if cfg!(target_os = "windows") {
"Segoe UI".into()
"Consolas".into()
} else {
"FreeMono".into()
"DejaVu Sans Mono".into()
},
mono_font_size: px(13.),
radius: px(6.),
radius_lg: px(8.),
shadow: true,

View file

@ -41,6 +41,15 @@ pub struct ThemeConfig {
/// The base font family, default is system font: `.SystemUIFont`.
#[serde(rename = "font.family")]
pub font_family: Option<SharedString>,
/// The monospace font family, default is platform specific:
/// - macOS: `Menlo`
/// - Windows: `Consolas`
/// - Linux: `DejaVu Sans Mono`
#[serde(rename = "mono_font.family")]
pub mono_font_family: Option<SharedString>,
/// The monospace font size, default is 13.
#[serde(rename = "mono_font.size")]
pub mono_font_size: Option<f32>,
/// The border radius for general elements, default is 6.
#[serde(rename = "radius")]
@ -652,6 +661,16 @@ impl Theme {
} else {
self.font_family = default_theme.font_family.clone();
}
if let Some(mono_font_family) = &config.mono_font_family {
self.mono_font_family = mono_font_family.clone();
} else {
self.mono_font_family = default_theme.mono_font_family.clone();
}
if let Some(mono_font_size) = config.mono_font_size {
self.mono_font_size = px(mono_font_size);
} else {
self.mono_font_size = default_theme.mono_font_size;
}
if let Some(radius) = config.radius {
self.radius = px(radius as f32);
} else {

View file

@ -89,7 +89,7 @@ impl Render for Tooltip {
div().child(
// Wrap in a child, to ensure the left margin is applied to the tooltip
h_flex()
.font_family(".SystemUIFont")
.font_family(cx.theme().font_family.clone())
.m_3()
.bg(cx.theme().popover)
.text_color(cx.theme().popover_foreground)