Skip to content

Commit ac4780f

Browse files
authored
fix(web): restore typography font sizes to defaults (#6172)
1 parent 3da7f9c commit ac4780f

3 files changed

Lines changed: 110 additions & 16 deletions

File tree

apps/web/src/components/settings/SettingsPanels.logic.test.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,26 @@ import {
1212
backgroundActivitySharedPolicySettings,
1313
buildProviderInstanceUpdatePatch,
1414
formatDiagnosticsDescription,
15+
getChangedTypographySettingLabels,
1516
hasChangedBackgroundActivitySettings,
1617
isProjectGroupingEnabled,
1718
projectGroupingModeFromToggle,
1819
resolveBackgroundActivityProfileOption,
1920
} from "./SettingsPanels.logic";
2021

22+
describe("typography settings restore", () => {
23+
it("detects family and size changes by font row", () => {
24+
expect(getChangedTypographySettingLabels(DEFAULT_UNIFIED_SETTINGS)).toEqual([]);
25+
expect(
26+
getChangedTypographySettingLabels({
27+
...DEFAULT_UNIFIED_SETTINGS,
28+
fontSizeInterface: 18,
29+
fontFamilyCode: "Fira Code",
30+
}),
31+
).toEqual(["Interface font", "Code font"]);
32+
});
33+
});
34+
2135
describe("background activity settings restore", () => {
2236
it("detects legacy interval values even when the structured setting is at its default", () => {
2337
expect(

apps/web/src/components/settings/SettingsPanels.logic.ts

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,40 @@ export function hasChangedBackgroundActivitySettings(
7474
);
7575
}
7676

77+
type TypographySettings = Pick<
78+
UnifiedSettings,
79+
| "fontFamilySans"
80+
| "fontFamilyComposer"
81+
| "fontFamilyCode"
82+
| "fontFamilyTerminal"
83+
| "fontSizeInterface"
84+
| "fontSizePrompt"
85+
| "fontSizeCode"
86+
| "fontSizeTerminal"
87+
>;
88+
89+
/** Labels the font rows whose family or size differs from the defaults. */
90+
export function getChangedTypographySettingLabels(settings: TypographySettings): string[] {
91+
return [
92+
...(settings.fontFamilySans !== DEFAULT_UNIFIED_SETTINGS.fontFamilySans ||
93+
settings.fontSizeInterface !== DEFAULT_UNIFIED_SETTINGS.fontSizeInterface
94+
? ["Interface font"]
95+
: []),
96+
...(settings.fontFamilyComposer !== DEFAULT_UNIFIED_SETTINGS.fontFamilyComposer ||
97+
settings.fontSizePrompt !== DEFAULT_UNIFIED_SETTINGS.fontSizePrompt
98+
? ["Prompt font"]
99+
: []),
100+
...(settings.fontFamilyCode !== DEFAULT_UNIFIED_SETTINGS.fontFamilyCode ||
101+
settings.fontSizeCode !== DEFAULT_UNIFIED_SETTINGS.fontSizeCode
102+
? ["Code font"]
103+
: []),
104+
...(settings.fontFamilyTerminal !== DEFAULT_UNIFIED_SETTINGS.fontFamilyTerminal ||
105+
settings.fontSizeTerminal !== DEFAULT_UNIFIED_SETTINGS.fontSizeTerminal
106+
? ["Terminal font"]
107+
: []),
108+
];
109+
}
110+
77111
export function resolveBackgroundActivityProfileOption(
78112
settings: ServerSettings,
79113
): BackgroundActivityProfile | "advanced" {

apps/web/src/components/settings/SettingsPanels.tsx

Lines changed: 62 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,7 @@ import {
122122
backgroundActivitySharedPolicySettings,
123123
durationToSeconds,
124124
formatDiagnosticsDescription,
125+
getChangedTypographySettingLabels,
125126
normalizeIntervalSeconds,
126127
PROVIDER_HEALTH_INTERVAL_STEP_SECONDS,
127128
hasChangedBackgroundActivitySettings,
@@ -493,16 +494,7 @@ export function useSettingsRestore(onRestored?: () => void) {
493494
? ["Auto-settle inactive threads"]
494495
: []),
495496
...(settings.wordWrap !== DEFAULT_UNIFIED_SETTINGS.wordWrap ? ["Word wrap"] : []),
496-
...(settings.fontFamilySans !== DEFAULT_UNIFIED_SETTINGS.fontFamilySans
497-
? ["Interface font"]
498-
: []),
499-
...(settings.fontFamilyComposer !== DEFAULT_UNIFIED_SETTINGS.fontFamilyComposer
500-
? ["Prompt font"]
501-
: []),
502-
...(settings.fontFamilyCode !== DEFAULT_UNIFIED_SETTINGS.fontFamilyCode ? ["Code font"] : []),
503-
...(settings.fontFamilyTerminal !== DEFAULT_UNIFIED_SETTINGS.fontFamilyTerminal
504-
? ["Terminal font"]
505-
: []),
497+
...getChangedTypographySettingLabels(settings),
506498
...(settings.diffIgnoreWhitespace !== DEFAULT_UNIFIED_SETTINGS.diffIgnoreWhitespace
507499
? ["Diff whitespace changes"]
508500
: []),
@@ -652,6 +644,10 @@ export function useSettingsRestore(onRestored?: () => void) {
652644
fontFamilyComposer: DEFAULT_UNIFIED_SETTINGS.fontFamilyComposer,
653645
fontFamilyCode: DEFAULT_UNIFIED_SETTINGS.fontFamilyCode,
654646
fontFamilyTerminal: DEFAULT_UNIFIED_SETTINGS.fontFamilyTerminal,
647+
fontSizeInterface: DEFAULT_UNIFIED_SETTINGS.fontSizeInterface,
648+
fontSizePrompt: DEFAULT_UNIFIED_SETTINGS.fontSizePrompt,
649+
fontSizeCode: DEFAULT_UNIFIED_SETTINGS.fontSizeCode,
650+
fontSizeTerminal: DEFAULT_UNIFIED_SETTINGS.fontSizeTerminal,
655651
});
656652
onRestored?.();
657653
}, [
@@ -1105,13 +1101,21 @@ function InterfaceFontRow({ preview }: { preview?: ReactNode }) {
11051101
{...searchableSetting("interface-font")}
11061102
description="Everything outside code blocks and the terminal."
11071103
defaultFamily={defaults.sans}
1104+
defaultValue={DEFAULT_UNIFIED_SETTINGS.fontFamilySans}
11081105
value={settings.fontFamilySans}
11091106
onValueChange={(fontFamilySans) => updateSettings({ fontFamilySans })}
1107+
onReset={() =>
1108+
updateSettings({
1109+
fontFamilySans: DEFAULT_UNIFIED_SETTINGS.fontFamilySans,
1110+
fontSizeInterface: DEFAULT_UNIFIED_SETTINGS.fontSizeInterface,
1111+
})
1112+
}
11101113
size={{
11111114
label: "Interface font size",
11121115
min: MIN_INTERFACE_FONT_SIZE,
11131116
max: MAX_INTERFACE_FONT_SIZE,
11141117
value: settings.fontSizeInterface,
1118+
defaultValue: DEFAULT_UNIFIED_SETTINGS.fontSizeInterface,
11151119
onChange: (fontSizeInterface) => updateSettings({ fontSizeInterface }),
11161120
}}
11171121
{...(preview !== undefined ? { preview } : {})}
@@ -1128,13 +1132,21 @@ function PromptFontRow() {
11281132
{...searchableSetting("prompt-font")}
11291133
description="Only the box you write prompts in. Mono works well here."
11301134
defaultFamily={defaults.interfaceFamily}
1135+
defaultValue={DEFAULT_UNIFIED_SETTINGS.fontFamilyComposer}
11311136
value={settings.fontFamilyComposer}
11321137
onValueChange={(fontFamilyComposer) => updateSettings({ fontFamilyComposer })}
1138+
onReset={() =>
1139+
updateSettings({
1140+
fontFamilyComposer: DEFAULT_UNIFIED_SETTINGS.fontFamilyComposer,
1141+
fontSizePrompt: DEFAULT_UNIFIED_SETTINGS.fontSizePrompt,
1142+
})
1143+
}
11331144
size={{
11341145
label: "Prompt font size",
11351146
min: MIN_PROMPT_FONT_SIZE,
11361147
max: MAX_PROMPT_FONT_SIZE,
11371148
value: settings.fontSizePrompt,
1149+
defaultValue: DEFAULT_UNIFIED_SETTINGS.fontSizePrompt,
11381150
onChange: (fontSizePrompt) => updateSettings({ fontSizePrompt }),
11391151
}}
11401152
preview={<PromptFontPreview />}
@@ -1160,14 +1172,22 @@ function CodeFontRow({
11601172
{...(title !== undefined ? { title } : {})}
11611173
description={description}
11621174
defaultFamily={defaults.code}
1175+
defaultValue={DEFAULT_UNIFIED_SETTINGS.fontFamilyCode}
11631176
value={settings.fontFamilyCode}
11641177
onValueChange={(fontFamilyCode) => updateSettings({ fontFamilyCode })}
1178+
onReset={() =>
1179+
updateSettings({
1180+
fontFamilyCode: DEFAULT_UNIFIED_SETTINGS.fontFamilyCode,
1181+
fontSizeCode: DEFAULT_UNIFIED_SETTINGS.fontSizeCode,
1182+
})
1183+
}
11651184
requireMonospace
11661185
size={{
11671186
label: "Code font size",
11681187
min: MIN_CODE_FONT_SIZE,
11691188
max: MAX_CODE_FONT_SIZE,
11701189
value: settings.fontSizeCode,
1190+
defaultValue: DEFAULT_UNIFIED_SETTINGS.fontSizeCode,
11711191
onChange: (fontSizeCode) => updateSettings({ fontSizeCode }),
11721192
}}
11731193
preview={preview ?? <CodeFontPreview />}
@@ -1184,14 +1204,22 @@ function TerminalFontRow() {
11841204
{...searchableSetting("terminal-font")}
11851205
description="Terminal output, independent from code blocks and diffs."
11861206
defaultFamily={defaults.code}
1207+
defaultValue={DEFAULT_UNIFIED_SETTINGS.fontFamilyTerminal}
11871208
value={settings.fontFamilyTerminal}
11881209
onValueChange={(fontFamilyTerminal) => updateSettings({ fontFamilyTerminal })}
1210+
onReset={() =>
1211+
updateSettings({
1212+
fontFamilyTerminal: DEFAULT_UNIFIED_SETTINGS.fontFamilyTerminal,
1213+
fontSizeTerminal: DEFAULT_UNIFIED_SETTINGS.fontSizeTerminal,
1214+
})
1215+
}
11891216
requireMonospace
11901217
size={{
11911218
label: "Terminal font size",
11921219
min: MIN_TERMINAL_FONT_SIZE,
11931220
max: MAX_TERMINAL_FONT_SIZE,
11941221
value: settings.fontSizeTerminal,
1222+
defaultValue: DEFAULT_UNIFIED_SETTINGS.fontSizeTerminal,
11951223
onChange: (fontSizeTerminal) => updateSettings({ fontSizeTerminal }),
11961224
}}
11971225
preview={
@@ -1369,9 +1397,11 @@ function FontFamilySettingsRow({
13691397
title,
13701398
description,
13711399
defaultFamily,
1400+
defaultValue,
13721401
preview,
13731402
value,
13741403
onValueChange,
1404+
onReset,
13751405
requireMonospace = false,
13761406
size,
13771407
}: {
@@ -1380,11 +1410,21 @@ function FontFamilySettingsRow({
13801410
description: string;
13811411
/** What an unset preference renders as, e.g. "Menlo". */
13821412
defaultFamily: string;
1413+
/** The persisted family value supplied by the unified settings defaults. */
1414+
defaultValue: string;
13831415
preview?: ReactNode;
13841416
value: string;
13851417
onValueChange: (value: string) => void;
1418+
onReset: () => void;
13861419
requireMonospace?: boolean;
1387-
size: { label: string; min: number; max: number; value: number; onChange: (v: number) => void };
1420+
size: {
1421+
label: string;
1422+
min: number;
1423+
max: number;
1424+
value: number;
1425+
defaultValue: number;
1426+
onChange: (v: number) => void;
1427+
};
13881428
}) {
13891429
const trimmed = value.trim();
13901430
// The fallback input edits a draft; the preference only commits once typing
@@ -1431,12 +1471,18 @@ function FontFamilySettingsRow({
14311471
// Flag an unknown name only once typing pauses, and never for an empty
14321472
// field - that is the starting state, not a rejected entry.
14331473
const draftPending = draftSettled && draftTrimmed.length > 0 && draftTrimmed !== trimmed;
1474+
const resetToDefault = () => {
1475+
if (commitTimerRef.current !== null) {
1476+
window.clearTimeout(commitTimerRef.current);
1477+
commitTimerRef.current = null;
1478+
}
1479+
setDraft(defaultValue);
1480+
setDraftSettled(true);
1481+
onReset();
1482+
};
14341483
const resetAction =
1435-
trimmed.length > 0 ? (
1436-
<SettingResetButton
1437-
label={`${title.toLowerCase()} family`}
1438-
onClick={() => onValueChange("")}
1439-
/>
1484+
value !== defaultValue || size.value !== size.defaultValue ? (
1485+
<SettingResetButton label={title.toLowerCase()} onClick={resetToDefault} />
14401486
) : null;
14411487
const fontEnumeration = useFontEnumeration();
14421488
// Everyone starts on the plain input; focusing it is the user gesture that

0 commit comments

Comments
 (0)