From 5bfff9d5e02f9570e8c1b8d770fec4b66694958a Mon Sep 17 00:00:00 2001 From: Hikari Date: Tue, 3 Mar 2026 18:07:14 -0800 Subject: [PATCH] feat: allow users to specify a custom font (closes #176) Adds support for loading a custom font from either a remote URL or a local file path, and applying it to the terminal and input bar. - Rust: adds `custom_font_path` and `custom_font_family` fields to `HikariConfig` with `#[serde(default)]` for backwards compatibility - TypeScript: extends `HikariConfig` interface and `defaultConfig`; exports `applyCustomFont()` which injects an `@import` for CSS stylesheet URLs, a `@font-face` rule for direct font file URLs, or a base64 data URL `@font-face` for local files via Tauri `readFile`; adds `setCustomFont()` to the config store - Terminal.svelte and InputBar.svelte now use `--terminal-font-family` CSS variable (falls back to `monospace`) - ConfigSidebar.svelte: new "Custom Font" section with URL/path input, family name input, Apply + Reset buttons, and inline status feedback - `+page.svelte`: applies saved font on startup alongside theme/size - 14 new tests for `applyCustomFont` (all code paths) + 2 for `setCustomFont` --- src-tauri/src/config.rs | 13 ++ src/lib/components/ConfigSidebar.svelte | 70 +++++++++ src/lib/components/InputBar.svelte | 2 +- src/lib/components/StatusBar.svelte | 2 + src/lib/components/Terminal.svelte | 2 +- src/lib/stores/config.test.ts | 184 ++++++++++++++++++++++++ src/lib/stores/config.ts | 74 ++++++++++ src/routes/+page.svelte | 9 +- 8 files changed, 353 insertions(+), 3 deletions(-) diff --git a/src-tauri/src/config.rs b/src-tauri/src/config.rs index bdb10c5..dae5ac7 100644 --- a/src-tauri/src/config.rs +++ b/src-tauri/src/config.rs @@ -144,6 +144,13 @@ pub struct HikariConfig { #[serde(default)] pub show_thinking_blocks: bool, + + // Custom font settings + #[serde(default)] + pub custom_font_path: Option, + + #[serde(default)] + pub custom_font_family: Option, } impl Default for HikariConfig { @@ -183,6 +190,8 @@ impl Default for HikariConfig { background_image_path: None, background_image_opacity: 0.3, show_thinking_blocks: false, + custom_font_path: None, + custom_font_family: None, } } } @@ -298,6 +307,8 @@ mod tests { assert!(!config.disable_1m_context); assert!(config.trusted_workspaces.is_empty()); assert!(!config.show_thinking_blocks); + assert!(config.custom_font_path.is_none()); + assert!(config.custom_font_family.is_none()); } #[test] @@ -337,6 +348,8 @@ mod tests { background_image_path: Some("/home/naomi/bg.png".to_string()), background_image_opacity: 0.25, show_thinking_blocks: true, + custom_font_path: Some("/home/naomi/.fonts/MyFont.ttf".to_string()), + custom_font_family: Some("MyFont".to_string()), }; let json = serde_json::to_string(&config).unwrap(); diff --git a/src/lib/components/ConfigSidebar.svelte b/src/lib/components/ConfigSidebar.svelte index 0ea8270..8d5ff5e 100644 --- a/src/lib/components/ConfigSidebar.svelte +++ b/src/lib/components/ConfigSidebar.svelte @@ -5,6 +5,7 @@ type Theme, type CustomThemeColors, applyFontSize, + applyCustomFont, applyCustomThemeColors, MIN_FONT_SIZE, MAX_FONT_SIZE, @@ -60,9 +61,14 @@ trusted_workspaces: [], background_image_path: null, background_image_opacity: 0.3, + custom_font_path: null, + custom_font_family: null, }); let showCustomThemeEditor = $state(false); + let customFontPathInput = $state(""); + let customFontFamilyInput = $state(""); + let customFontStatus: string | null = $state(null); interface AuthStatus { is_logged_in: boolean; @@ -88,6 +94,8 @@ configStore.config.subscribe((c) => { config = { ...c }; + customFontPathInput = c.custom_font_path ?? ""; + customFontFamilyInput = c.custom_font_family ?? ""; }); configStore.isSidebarOpen.subscribe((open) => { @@ -937,6 +945,68 @@

+ +
+ Custom Font +
+ + +
+ + +
+ {#if customFontStatus} +

{customFontStatus}

+ {/if} +
+

+ Supports Google Fonts URLs, direct font file URLs, or local file paths. Family name is + required to apply the font. +

+
+