Add terminal font customization options#300

closed3
main
GitHub fork: main
openedMar 7, 2026byGGearHead87
View on GitHubTwo-way sync enabledPR last imported 21d ago

Summary

  • add terminal font family and font size preferences to app settings
  • apply terminal typography changes live in the terminal drawer, including refit and resize handling
  • add validation and tests for terminal font family fallback and font size clamping

Why

This makes terminal panes easier to read and lets users match the terminal to their preferred coding setup without requiring any manual app configuration. I just want to use my Nerd Fonts from my system.

Screenshots

Default Fonts

# After Adding Nerd Font

Note

Add terminal font customization by persisting AppSettingsSchema fields and wiring them to ThreadTerminalDrawer and TerminalViewport

Add terminalFontFamily, terminalFontSize (clamped to min/max and rounded), and terminalLineHeight (clamped and rounded to 2 decimals) to settings; normalize via resolveTerminalFontFamily, clampTerminalFontSize, and resolveTerminalLineHeight; export parsePersistedSettings; pass settings into the terminal and update live; expose inputs in the chat settings UI.

πŸ“Where to Start

Start with normalizeAppSettings and new terminal typography utils in apps/web/src/appSettings.ts, then review their use in ThreadTerminalDrawer and TerminalViewport in apps/web/src/components/ThreadTerminalDrawer.tsx.

Macroscope summarized db68d11.

Added 1 commit

  • Add terminal font customization options6eb4e11
Synced from GitHub

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

βš™οΈ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 25a1931a-5422-41b8-b9c6-141bd08c5391

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • πŸ” Trigger review
✨ Finishing Touches
πŸ§ͺ Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❀️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

apps/web/src/appSettings.tslines 57–63Outdated Β· 6eb4e11Open thread
……@@ -45,6 +51,15 @@ const AppSettingsSchema = Schema.Struct({
60+ maximum: MAX_TERMINAL_FONT_SIZE,
61+ }),
62+ ).pipe(Schema.withConstructorDefault(() => Option.some(DEFAULT_TERMINAL_FONT_SIZE))),
4863});
MmacroscopeappBoton lines 57–63Mar 7, 2026

🟠 High src/appSettings.ts:57

The terminalFontSize schema uses Schema.Int with Schema.isBetween, so Schema.decodeSync throws on values outside [8,32] or non-integers before normalizeAppSettings can run. This causes updateSettings to crash on raw input that needs clamping, and parsePersistedSettings to discard all user settings if localStorage contains an out-of-bounds font size. Consider relaxing the schema to Schema.Number so clampTerminalFontSize can handle rounding and clamping after decode succeeds.

Also found in 1 other location(s)

apps/web/src/routes/_chat.settings.tsx:347

The terminalFontSize input field is unusable for typing most values due to aggressive clamping in the onChange handler. When a user types a number, clampTerminalFontSize is called immediately on the incomplete value. Since MIN_TERMINAL_FONT_SIZE is 8, typing a starting digit like "1" (intending to type "12" or "14") results in the value being immediately clamped to 8 and the input updating to display "8". Appending a digit then results in a number like "84", which gets clamped to the maximum of 32. Additionally, the !Number.isFinite(next) check prevents the user from clearing the input field, as the state update is skipped while the component re-renders with the old valid value.

βœ… Resolved in db68d1145a1c263d907c58e097d36cffca34a8be

Added 2 commits

  • Enhance terminal font settings functionality58acf26
  • Enhance terminal line height settingsdb68d11
apps/web/src/appSettings.tslines 57–65Open thread
……@@ -45,6 +54,15 @@ const AppSettingsSchema = Schema.Struct({
62+ ),
63+ terminalLineHeight: Schema.Number.pipe(
64+ Schema.withConstructorDefault(() => Option.some(DEFAULT_TERMINAL_LINE_HEIGHT)),
65+ ),
MmacroscopeappBoton lines 57–65Mar 7, 2026

🟠 High src/appSettings.ts:57

Adding terminalFontFamily, terminalFontSize, and terminalLineHeight as required fields causes Schema.decodeSync in parsePersistedSettings to throw for existing users whose stored settings lack these fields. The catch block then returns DEFAULT_APP_SETTINGS, silently discarding all previously saved user data including customCodexModels and paths. Consider defining these fields as optional so decoding succeeds and defaults are applied only to missing fields, preventing data loss on the next load.

diff
1- terminalFontFamily: Schema.String.check(Schema.isMaxLength(MAX_TERMINAL_FONT_FAMILY_LENGTH)).pipe(
2- Schema.withConstructorDefault(() => Option.some(DEFAULT_TERMINAL_FONT_FAMILY)),
3- ),
4- terminalFontSize: Schema.Number.pipe(
5- Schema.withConstructorDefault(() => Option.some(DEFAULT_TERMINAL_FONT_SIZE)),
6- ),
7- terminalLineHeight: Schema.Number.pipe(
8- Schema.withConstructorDefault(() => Option.some(DEFAULT_TERMINAL_LINE_HEIGHT)),
9- ),
πŸš€ Reply "fix it for me" or copy this AI Prompt for your agent:
text
1In file apps/web/src/appSettings.ts around lines 57-65:
2
3Adding `terminalFontFamily`, `terminalFontSize`, and `terminalLineHeight` as required fields causes `Schema.decodeSync` in `parsePersistedSettings` to throw for existing users whose stored settings lack these fields. The catch block then returns `DEFAULT_APP_SETTINGS`, silently discarding all previously saved user data including `customCodexModels` and paths. Consider defining these fields as optional so decoding succeeds and defaults are applied only to missing fields, preventing data loss on the next load.
4
5Evidence trail:
6apps/web/src/appSettings.ts lines 54-64 (new fields with withConstructorDefault); apps/web/src/appSettings.ts lines 253-264 (parsePersistedSettings function); git_diff base=MERGE_BASE head=REVIEWED_COMMIT path=apps/web/src/appSettings.ts; Effect Schema documentation at https://github.com/xstelea/radix-context/blob/main/context/effect-Schema.md (section 'Defaults (Constructor and Decoding)' explains withConstructorDefault vs optionalWith behavior)

There are no existing users yet since the app is in alpha. While this is a valid concern, we can disregard it for now.