mirror of
https://github.com/Termix-SSH/Termix.git
synced 2026-08-27 00:17:05 +00:00
Add accessible interface font choices (#1306)
This commit is contained in:
+6
-2
@@ -9,9 +9,9 @@ import { isElectron } from "@/lib/electron";
|
||||
import { Toaster } from "@/components/sonner";
|
||||
import { Auth, getStoredAuth, clearStoredAuth } from "@/auth/Auth";
|
||||
import { getUserInfo, getCurrentToken, appReadyPromise } from "@/main-axios";
|
||||
import { applyAccentColor, applyFontSize } from "@/lib/theme";
|
||||
import { applyAccentColor, applyFontSize, applyUiFont } from "@/lib/theme";
|
||||
import { installElectronWheelZoomGuard } from "@/lib/electron-wheel-zoom";
|
||||
import type { FontSizeId } from "@/types/ui-types";
|
||||
import type { FontSizeId, UiFontId } from "@/types/ui-types";
|
||||
import { useServiceWorker } from "@/hooks/use-service-worker";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { UiPreferencesProvider } from "@/contexts/UiPreferencesContext";
|
||||
@@ -202,6 +202,10 @@ function App() {
|
||||
"termix-font-size",
|
||||
) as FontSizeId | null;
|
||||
applyFontSize(savedSize ?? "md");
|
||||
applyUiFont(
|
||||
(localStorage.getItem("termix-ui-font") as UiFontId | null) ??
|
||||
"jetbrains-mono",
|
||||
);
|
||||
return () => {
|
||||
if (timerRef.current) clearTimeout(timerRef.current);
|
||||
};
|
||||
|
||||
@@ -357,6 +357,12 @@ export type ThemeId =
|
||||
| "one-dark"
|
||||
| "gruvbox";
|
||||
export type FontSizeId = "xs" | "sm" | "md" | "lg" | "xl";
|
||||
export type UiFontId =
|
||||
| "jetbrains-mono"
|
||||
| "system-sans"
|
||||
| "fira-code"
|
||||
| "source-code-pro"
|
||||
| "caskaydia-cove";
|
||||
|
||||
export type ToolsTab =
|
||||
"ssh-tools" | "snippets" | "macros" | "history" | "split-screen";
|
||||
|
||||
@@ -861,6 +861,7 @@ export function AppShell({
|
||||
const SNAPSHOT_KEYS = [
|
||||
"termix-accent",
|
||||
"termix-font-size",
|
||||
"termix-ui-font",
|
||||
"i18nextLng",
|
||||
"commandAutocomplete",
|
||||
"commandPaletteShortcutEnabled",
|
||||
|
||||
+1
-1
@@ -55,7 +55,7 @@
|
||||
|
||||
@theme inline {
|
||||
--font-heading: var(--font-mono);
|
||||
--font-mono: "JetBrains Mono Variable", monospace;
|
||||
--font-mono: var(--font-ui, "JetBrains Mono Variable", monospace);
|
||||
--color-accent-brand: var(--accent-brand);
|
||||
--color-sidebar-ring: var(--sidebar-ring);
|
||||
--color-sidebar-border: var(--sidebar-border);
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import type {
|
||||
DashboardCardConfig,
|
||||
FontSizeId,
|
||||
UiFontId,
|
||||
SplitMode,
|
||||
} from "@/types/ui-types";
|
||||
|
||||
@@ -89,6 +90,40 @@ export function applyFontSize(id: FontSizeId) {
|
||||
localStorage.setItem("termix-font-size", id);
|
||||
}
|
||||
|
||||
export const UI_FONTS: { id: UiFontId; label: string; family: string }[] = [
|
||||
{
|
||||
id: "jetbrains-mono",
|
||||
label: "JetBrains Mono",
|
||||
family: '"JetBrains Mono Variable", monospace',
|
||||
},
|
||||
{
|
||||
id: "system-sans",
|
||||
label: "System Sans",
|
||||
family: "ui-sans-serif, system-ui, sans-serif",
|
||||
},
|
||||
{
|
||||
id: "fira-code",
|
||||
label: "Fira Code",
|
||||
family: '"Fira Code", monospace',
|
||||
},
|
||||
{
|
||||
id: "source-code-pro",
|
||||
label: "Source Code Pro",
|
||||
family: '"Source Code Pro", monospace',
|
||||
},
|
||||
{
|
||||
id: "caskaydia-cove",
|
||||
label: "Caskaydia Cove",
|
||||
family: '"Caskaydia Cove Nerd Font Mono", monospace',
|
||||
},
|
||||
];
|
||||
|
||||
export function applyUiFont(id: UiFontId) {
|
||||
const font = UI_FONTS.find((candidate) => candidate.id === id) ?? UI_FONTS[0];
|
||||
document.documentElement.style.setProperty("--font-ui", font.family);
|
||||
localStorage.setItem("termix-ui-font", font.id);
|
||||
}
|
||||
|
||||
export const FOLDER_COLORS = [
|
||||
"#ef4444",
|
||||
"#f97316",
|
||||
|
||||
@@ -4150,6 +4150,8 @@
|
||||
"languageLabel": "Language",
|
||||
"themeLabel": "Theme",
|
||||
"fontSizeLabel": "Font Size",
|
||||
"interfaceFontLabel": "Interface Font",
|
||||
"interfaceFontDescription": "Changes the application interface font. Terminal profiles keep their own font settings.",
|
||||
"accentColorLabel": "Accent Color",
|
||||
"settingsTerminal": "Terminal",
|
||||
"commandAutocomplete": "Command Autocomplete",
|
||||
|
||||
@@ -77,11 +77,13 @@ import {
|
||||
ACCENT_PRESET_COLORS,
|
||||
applyAccentColor,
|
||||
applyFontSize,
|
||||
applyUiFont,
|
||||
FONT_SIZES,
|
||||
UI_FONTS,
|
||||
} from "@/lib/theme";
|
||||
import type { ApiKey } from "@/main-axios";
|
||||
import { useTheme } from "@/components/theme-provider";
|
||||
import type { FontSizeId, ThemeId } from "@/types/ui-types";
|
||||
import type { FontSizeId, ThemeId, UiFontId } from "@/types/ui-types";
|
||||
import { toast } from "sonner";
|
||||
import { changeAppLanguage, normalizeLanguageCode } from "@/i18n/i18n";
|
||||
import { clearLocalAdaptivePreferences } from "@/lib/local-adaptive-preferences";
|
||||
@@ -597,6 +599,10 @@ export function UserProfilePanel({
|
||||
const [fontSize, setFontSize] = useState<FontSizeId>(
|
||||
() => (localStorage.getItem("termix-font-size") as FontSizeId) ?? "md",
|
||||
);
|
||||
const [uiFont, setUiFont] = useState<UiFontId>(
|
||||
() =>
|
||||
(localStorage.getItem("termix-ui-font") as UiFontId) ?? "jetbrains-mono",
|
||||
);
|
||||
const [language, setLanguage] = useState(() =>
|
||||
normalizeLanguageCode(localStorage.getItem("i18nextLng")),
|
||||
);
|
||||
@@ -831,6 +837,7 @@ export function UserProfilePanel({
|
||||
const SNAPSHOT_KEYS = [
|
||||
"termix-accent",
|
||||
"termix-font-size",
|
||||
"termix-ui-font",
|
||||
"i18nextLng",
|
||||
"commandAutocomplete",
|
||||
"commandPaletteShortcutEnabled",
|
||||
@@ -961,6 +968,8 @@ export function UserProfilePanel({
|
||||
setTheme("system");
|
||||
setFontSize("md");
|
||||
applyFontSize("md");
|
||||
setUiFont("jetbrains-mono");
|
||||
applyUiFont("jetbrains-mono");
|
||||
setAccentColor(DEFAULT_ACCENT);
|
||||
setCustomColorInput(DEFAULT_ACCENT);
|
||||
localStorage.setItem("termix-accent", DEFAULT_ACCENT);
|
||||
@@ -1047,6 +1056,12 @@ export function UserProfilePanel({
|
||||
setFontSize(restoredFontSize);
|
||||
applyFontSize(restoredFontSize);
|
||||
|
||||
const restoredUiFont =
|
||||
(restore("termix-ui-font", "jetbrains-mono") as UiFontId) ??
|
||||
"jetbrains-mono";
|
||||
setUiFont(restoredUiFont);
|
||||
applyUiFont(restoredUiFont);
|
||||
|
||||
const restoredAccent = restore("termix-accent", "#f59145") ?? "#f59145";
|
||||
setAccentColor(restoredAccent);
|
||||
setCustomColorInput(restoredAccent);
|
||||
@@ -1156,6 +1171,11 @@ export function UserProfilePanel({
|
||||
if (storageMode === "cloud") saveToCloud({ fontSize: id });
|
||||
}
|
||||
|
||||
function handleUiFontChange(id: UiFontId) {
|
||||
setUiFont(id);
|
||||
applyUiFont(id);
|
||||
}
|
||||
|
||||
function handleLanguageChange(code: string) {
|
||||
void changeAppLanguage(code)
|
||||
.then((language) => {
|
||||
@@ -1723,6 +1743,29 @@ export function UserProfilePanel({
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="flex flex-col gap-1.5">
|
||||
<span className="text-[10px] font-bold uppercase tracking-widest text-muted-foreground flex items-center gap-1.5">
|
||||
<Type className="size-3" />
|
||||
{t("newUi.sidebar.userProfile.interfaceFontLabel")}
|
||||
</span>
|
||||
<select
|
||||
value={uiFont}
|
||||
onChange={(event) =>
|
||||
handleUiFontChange(event.target.value as UiFontId)
|
||||
}
|
||||
className="px-2.5 py-1.5 text-xs bg-background border border-border text-foreground outline-none focus:ring-1 focus:ring-ring w-full"
|
||||
>
|
||||
{UI_FONTS.map((font) => (
|
||||
<option key={font.id} value={font.id}>
|
||||
{font.label}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
<span className="text-[10px] text-muted-foreground">
|
||||
{t("newUi.sidebar.userProfile.interfaceFontDescription")}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div className="flex flex-col gap-1.5">
|
||||
<span className="text-[10px] font-bold uppercase tracking-widest text-muted-foreground flex items-center gap-1.5">
|
||||
<Type className="size-3" />
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
import { beforeEach, describe, expect, it } from "vitest";
|
||||
import { applyUiFont } from "../../lib/theme";
|
||||
|
||||
describe("applyUiFont", () => {
|
||||
beforeEach(() => {
|
||||
localStorage.clear();
|
||||
document.documentElement.style.removeProperty("--font-ui");
|
||||
});
|
||||
|
||||
it("applies and persists a readable system font", () => {
|
||||
applyUiFont("system-sans");
|
||||
|
||||
expect(document.documentElement.style.getPropertyValue("--font-ui")).toBe(
|
||||
"ui-sans-serif, system-ui, sans-serif",
|
||||
);
|
||||
expect(localStorage.getItem("termix-ui-font")).toBe("system-sans");
|
||||
});
|
||||
|
||||
it("falls back to JetBrains Mono for an unknown stored value", () => {
|
||||
applyUiFont("unknown" as never);
|
||||
|
||||
expect(localStorage.getItem("termix-ui-font")).toBe("jetbrains-mono");
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user