From c3a6a2950aa93127b04066ea764c9781b2b96137 Mon Sep 17 00:00:00 2001
From: Hikari
Date: Tue, 3 Mar 2026 19:36:35 -0800
Subject: [PATCH] fix: apply custom UI font to full app interface
- Set document.body.style.fontFamily directly (belt-and-suspenders
alongside the CSS variable) to ensure the font propagates
- Use var(--ui-font-family) in .app-container so the main app area
respects the custom font (was hardcoded, blocking inheritance)
- Rename 'Custom Font' setting to 'Custom Terminal Font' for clarity
---
src/lib/components/ConfigSidebar.svelte | 4 ++--
src/lib/stores/config.test.ts | 32 +++++++++++++++++++------
src/lib/stores/config.ts | 11 +++++----
src/routes/+page.svelte | 6 +++--
4 files changed, 38 insertions(+), 15 deletions(-)
diff --git a/src/lib/components/ConfigSidebar.svelte b/src/lib/components/ConfigSidebar.svelte
index 0047489..1328fbb 100644
--- a/src/lib/components/ConfigSidebar.svelte
+++ b/src/lib/components/ConfigSidebar.svelte
@@ -953,9 +953,9 @@
-
+
-
Custom Font
+
Custom Terminal Font
{
beforeEach(() => {
document.getElementById("hikari-custom-ui-font")?.remove();
document.documentElement.style.removeProperty("--ui-font-family");
+ document.body.style.removeProperty("font-family");
readFileMock.mockReset();
});
- it("removes CSS variable when both path and family are null", async () => {
+ it("removes CSS variable and body font-family when both path and family are null", async () => {
document.documentElement.style.setProperty("--ui-font-family", "'SomeFont', sans-serif");
+ document.body.style.setProperty("font-family", "'SomeFont', sans-serif");
await applyCustomUiFont(null, null);
expect(document.documentElement.style.getPropertyValue("--ui-font-family")).toBe("");
+ expect(document.body.style.getPropertyValue("font-family")).toBe("");
});
- it("removes CSS variable when both path and family are empty strings", async () => {
+ it("removes CSS variable and body font-family when both path and family are empty strings", async () => {
document.documentElement.style.setProperty("--ui-font-family", "'SomeFont', sans-serif");
+ document.body.style.setProperty("font-family", "'SomeFont', sans-serif");
await applyCustomUiFont("", "");
expect(document.documentElement.style.getPropertyValue("--ui-font-family")).toBe("");
+ expect(document.body.style.getPropertyValue("font-family")).toBe("");
expect(document.getElementById("hikari-custom-ui-font")).toBeNull();
});
- it("injects @import for a CSS stylesheet URL", async () => {
+ it("injects @import for a CSS stylesheet URL and applies font to body", async () => {
await applyCustomUiFont("https://fonts.googleapis.com/css2?family=Inter", "Inter");
const style = document.getElementById("hikari-custom-ui-font");
expect(style).not.toBeNull();
@@ -1357,9 +1362,10 @@ describe("config store", () => {
expect(document.documentElement.style.getPropertyValue("--ui-font-family")).toBe(
"'Inter', sans-serif"
);
+ expect(document.body.style.getPropertyValue("font-family")).toBe('"Inter", sans-serif');
});
- it("injects @font-face for a direct font file URL (.woff2)", async () => {
+ it("injects @font-face for a direct font file URL (.woff2) and applies font to body", async () => {
await applyCustomUiFont("https://example.com/fonts/Inter.woff2", "Inter");
const style = document.getElementById("hikari-custom-ui-font");
expect(style).not.toBeNull();
@@ -1368,15 +1374,19 @@ describe("config store", () => {
expect(document.documentElement.style.getPropertyValue("--ui-font-family")).toBe(
"'Inter', sans-serif"
);
+ expect(document.body.style.getPropertyValue("font-family")).toBe('"Inter", sans-serif');
});
- it("uses HikariCustomUiFont as fallback family for direct font URLs when family is empty", async () => {
+ it("uses HikariCustomUiFont as fallback family and applies it to body", async () => {
await applyCustomUiFont("https://example.com/fonts/Inter.woff2", "");
const style = document.getElementById("hikari-custom-ui-font");
expect(style?.textContent).toContain("'HikariCustomUiFont'");
+ expect(document.body.style.getPropertyValue("font-family")).toBe(
+ '"HikariCustomUiFont", sans-serif'
+ );
});
- it("reads local file and embeds as data URL", async () => {
+ it("reads local file and embeds as data URL, applies font to body", async () => {
const fakeData = new Uint8Array([104, 101, 108, 108, 111]);
readFileMock.mockResolvedValueOnce(fakeData);
@@ -1388,13 +1398,17 @@ describe("config store", () => {
expect(document.documentElement.style.getPropertyValue("--ui-font-family")).toBe(
"'Inter', sans-serif"
);
+ expect(document.body.style.getPropertyValue("font-family")).toBe('"Inter", sans-serif');
});
- it("sets CSS variable when only family is provided (no path)", async () => {
+ it("sets CSS variable and body font-family when only family is provided (no path)", async () => {
await applyCustomUiFont("", "SystemUiFont");
expect(document.documentElement.style.getPropertyValue("--ui-font-family")).toBe(
"'SystemUiFont', sans-serif"
);
+ expect(document.body.style.getPropertyValue("font-family")).toBe(
+ '"SystemUiFont", sans-serif'
+ );
});
it("replaces a previously injected style element", async () => {
@@ -1415,6 +1429,7 @@ describe("config store", () => {
beforeEach(() => {
document.getElementById("hikari-custom-ui-font")?.remove();
document.documentElement.style.removeProperty("--ui-font-family");
+ document.body.style.removeProperty("font-family");
readFileMock.mockReset();
invokeMock.mockResolvedValue(undefined);
});
@@ -1435,13 +1450,16 @@ describe("config store", () => {
expect(document.documentElement.style.getPropertyValue("--ui-font-family")).toBe(
"'Inter', sans-serif"
);
+ expect(document.body.style.getPropertyValue("font-family")).toBe('"Inter", sans-serif');
});
it("clears UI font when called with nulls", async () => {
document.documentElement.style.setProperty("--ui-font-family", "'SomeFont', sans-serif");
+ document.body.style.setProperty("font-family", "'SomeFont', sans-serif");
await configStore.setCustomUiFont(null, null);
expect(document.documentElement.style.getPropertyValue("--ui-font-family")).toBe("");
+ expect(document.body.style.getPropertyValue("font-family")).toBe("");
expect(invokeMock).toHaveBeenCalledWith(
"save_config",
expect.objectContaining({
diff --git a/src/lib/stores/config.ts b/src/lib/stores/config.ts
index 001d2f5..bd71637 100644
--- a/src/lib/stores/config.ts
+++ b/src/lib/stores/config.ts
@@ -404,16 +404,19 @@ export async function applyCustomUiFont(path: string | null, family: string | nu
if (!trimmedPath && !trimmedFamily) {
document.documentElement.style.removeProperty(cssVar);
+ document.body?.style.removeProperty("font-family");
return;
}
+ const effectiveFamily = trimmedFamily || fallbackFamily;
+
if (trimmedPath) {
- await applyFontFromSource(trimmedPath, trimmedFamily || fallbackFamily, styleId);
+ await applyFontFromSource(trimmedPath, effectiveFamily, styleId);
}
- if (trimmedFamily) {
- document.documentElement.style.setProperty(cssVar, `'${trimmedFamily}', sans-serif`);
- }
+ const fontValue = `'${effectiveFamily}', sans-serif`;
+ document.documentElement.style.setProperty(cssVar, fontValue);
+ document.body?.style.setProperty("font-family", fontValue);
}
export { MIN_FONT_SIZE, MAX_FONT_SIZE, DEFAULT_FONT_SIZE };
diff --git a/src/routes/+page.svelte b/src/routes/+page.svelte
index d2c777d..4fb5754 100644
--- a/src/routes/+page.svelte
+++ b/src/routes/+page.svelte
@@ -602,13 +602,15 @@