From b4742b730b656ccbc26a0ce6933ea063b356778c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=83=A1=E7=BF=80?= <1020327414@qq.com> Date: Tue, 27 Oct 2026 14:38:42 +0800 Subject: [PATCH] Support custom editor font weights in steps of 50 (#74) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit JetBrains Mono at 500 looks heavier than PyCharm's rendering, and 450 was rounded up to 500. Adds a Custom option with an input to the Main and Bold font weight rows; weights are clamped to 100–900 and rounded to the nearest 50 (the terminal, which follows the editor weights, gets the same steps). Verified in the app: Custom → 450 shows the input and the preview renders at 450. Maintainer follow-up: formatted the dialog test. Related: #32 https://claude.ai/code/session_01VUYsdXA2nkF5v6zsC93dpn --- .../settings/__tests__/dialog.test.tsx | 20 ++++++++ src/features/settings/pages/editor/font.tsx | 48 ++++++++++++------- src/platform/colorScheme.test.ts | 3 +- src/platform/editorSettings.ts | 4 +- 4 files changed, 54 insertions(+), 21 deletions(-) diff --git a/src/features/settings/__tests__/dialog.test.tsx b/src/features/settings/__tests__/dialog.test.tsx index 42591fcd..32ceed56 100644 --- a/src/features/settings/__tests__/dialog.test.tsx +++ b/src/features/settings/__tests__/dialog.test.tsx @@ -128,6 +128,26 @@ describe("Settings dialog", () => { ]); }); + it("edits and saves independent custom font weights", async () => { + const dialog = await openDialog("editor.font"); + for (const [label, value] of [ + ["Main font weight", "449"], + ["Bold font weight", "650"], + ]) { + fireEvent.click(within(dialog).getByRole("button", { name: label })); + fireEvent.click(screen.getByRole("option", { name: "Custom" })); + fireEvent.change(within(dialog).getByLabelText(`${label} custom value`), { target: { value } }); + } + const preview = within(dialog).getByLabelText("Font preview"); + expect(preview.style.getPropertyValue("--fw-code")).toBe("450"); + expect(preview.style.getPropertyValue("--fw-code-bold")).toBe("650"); + await act(async () => fireEvent.click(within(dialog).getByRole("button", { name: "Apply" }))); + expect(settingsSet.mock.calls).toEqual([ + ["global", "editor.boldFontWeight", "650"], + ["global", "editor.fontWeight", "450"], + ]); + }); + it("Cancel discards staged edits", async () => { const dialog = await openDialog("editor.codeStyle.other"); fireEvent.change(within(dialog).getByLabelText("Tab size"), { target: { value: "2" } }); diff --git a/src/features/settings/pages/editor/font.tsx b/src/features/settings/pages/editor/font.tsx index 3c422d86..25e0eb20 100644 --- a/src/features/settings/pages/editor/font.tsx +++ b/src/features/settings/pages/editor/font.tsx @@ -6,7 +6,7 @@ import { useMemo, useState } from "react"; import { Checkbox, type SelectOption, T } from "@/ui"; import { monoFontFamily } from "@/platform/fonts"; import { NumberInput, Row, SearchLabel, Select } from "../../components/Form"; -import { useLabelMatch, useSetting } from "../../components/context"; +import { useLabelMatch, usePageContext, useSetting } from "../../components/context"; import { FONT_WEIGHTS, fontWeightOf, fontWeightVars } from "@/platform/editorSettings"; import { LIMITS } from "../../model/schema"; import { editorPage } from "./kit"; @@ -135,7 +135,32 @@ function FallbackRow() { ); } -const WEIGHT_OPTIONS: SelectOption[] = FONT_WEIGHTS.map(([w, name]) => ({ value: String(w), label: name, detail: String(w) })); +const WEIGHT_OPTIONS: SelectOption[] = [ + ...FONT_WEIGHTS.map(([w, name]) => ({ value: String(w), label: name, detail: String(w) })), + { value: "custom", label: "Custom" }, +]; + +function WeightRow({ label, value, onChange, defaultWeight, hint }: { label: string; value: number; onChange: (value: number) => void; defaultWeight: number; hint?: string }) { + const [customSelected, setCustomSelected] = useState(false); + const weight = fontWeightOf(value, defaultWeight); + const custom = customSelected || !FONT_WEIGHTS.some(([w]) => w === weight); + return ( + + setMain(Number(v))} - aria-label="Main font weight" - /> - - -