feat(settings): add font size selector to Appearance settings#128
Conversation
📝 WalkthroughWalkthroughAdds a configurable Font size setting (10px–24px) persisted in localStorage and applied via CSS custom properties; converts many px font-size usages to rem across styles and components; adds UI controls in Appearance settings to choose base UI and editor font sizes. Changes
Sequence Diagram(s)sequenceDiagram
participant User
participant AppearanceSettings
participant SettingsContext
participant LocalStorage
participant DocumentRoot as "document.documentElement"
participant UIComponents
User->>AppearanceSettings: choose font size (InlineSelect)
AppearanceSettings->>SettingsContext: call setFontSize(size)
SettingsContext->>SettingsContext: normalize & clamp size
SettingsContext->>LocalStorage: write 'nerve:font-size'
SettingsContext->>DocumentRoot: setProperty('--font-size-base', size + 'px')
DocumentRoot->>UIComponents: rem-based styles reflow (implicit)
UIComponents-->>User: UI updated with new font sizing
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~28 minutes Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
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. Comment |
There was a problem hiding this comment.
Actionable comments posted: 3
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (3)
src/features/chat/components/ActivityLog.tsx (1)
19-19:⚠️ Potential issue | 🟠 MajorMixed sizing units here will drift with the new font-size setting.
The checkmark now scales via
rem, but row text is still locked tofontSize: '11px', so proportions will diverge as users change base font size. Convert the container font size to rem (or remove inline font sizing and use utilities) for consistent scaling.Proposed fix
- <div className="flex flex-col" style={{ fontFamily: 'var(--font-mono, monospace)', fontSize: '11px', lineHeight: 1.6 }}> + <div className="flex flex-col text-[0.6875rem]" style={{ fontFamily: 'var(--font-mono, monospace)', lineHeight: 1.6 }}>Also applies to: 35-35
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/features/chat/components/ActivityLog.tsx` at line 19, The container in ActivityLog is using a hard-coded pixel fontSize ('11px') which will desynchronize with the checkmark that uses rem; update the inline style on the outer div (the element rendering fontFamily and fontSize) to use rem units (e.g., fontSize: '0.6875rem') or remove the inline sizing and replace with a responsive Tailwind utility so text scales with root font-size; apply the same change to the other occurrence referenced around the row at the other location (the second styled div on line ~35) to keep proportions consistent.src/features/chat/components/ProcessingIndicator.tsx (2)
107-132:⚠️ Potential issue | 🟡 MinorAdditional inline
fontSize: '11px'values that won't scale.Lines 112 and 125 also use hardcoded
fontSize: '11px'inline styles for the recovery status and stale warning elements. These should be converted to Tailwind rem-based classes for consistency with the font scaling feature.🔧 Proposed fix
{/* Recovery status */} {isRecovering && ( <div - className="text-primary" - style={{ - fontSize: '11px', - paddingLeft: '2rem', - }} + className="text-primary text-[0.6875rem]" + style={{ paddingLeft: '2rem' }} > Resyncing transcript…{recoveryReason ? ` ${recoveryReason}` : ''} </div> )} {/* Stale warning */} {isStale && ( <div - className="text-orange" - style={{ - fontSize: '11px', - paddingLeft: '2rem', - animation: 'stale-pulse 2s ease-in-out infinite', - }} + className="text-orange text-[0.6875rem]" + style={{ paddingLeft: '2rem', animation: 'stale-pulse 2s ease-in-out infinite' }} > Still working… last update {secondsSinceEvent}s ago </div> )}🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/features/chat/components/ProcessingIndicator.tsx` around lines 107 - 132, The inline hardcoded fontSize: '11px' in the ProcessingIndicator component for the isRecovering and isStale blocks should be replaced with Tailwind rem-based classes to respect font scaling; update the JSX around isRecovering and isStale (the elements using recoveryReason and secondsSinceEvent) to remove the inline fontSize style and add an appropriate Tailwind utility class (e.g., text-xs or text-sm as needed) while keeping existing classes like text-primary and text-orange and retaining paddingLeft via existing className or convert to pl-8 to match the original spacing.
79-85:⚠️ Potential issue | 🟡 MinorInline
fontSize: '11px'overrides the rem-based class and won't scale.The Tailwind class
text-[0.75rem]on line 80 is immediately overridden by the inlinestyle={{ fontSize: '11px' }}on line 81. This hardcoded pixel value defeats the purpose of the rem conversion since inline styles take precedence and won't scale with--font-size-base.Consider removing the inline style and relying solely on the Tailwind class, or converting the inline style to rem:
🔧 Proposed fix
<div - className="break-all text-[0.75rem] text-muted-foreground" - style={{ fontSize: '11px', paddingLeft: '2rem' }} + className="break-all text-[0.6875rem] text-muted-foreground" + style={{ paddingLeft: '2rem' }} >🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/features/chat/components/ProcessingIndicator.tsx` around lines 79 - 85, In ProcessingIndicator, the inline style fontSize: '11px' overrides the Tailwind text-[0.75rem] class and prevents rem scaling; remove the inline fontSize (keep the Tailwind class) or replace it with a rem value, and convert paddingLeft: '2rem' to a Tailwind padding class (e.g., pl-8 or an appropriate pl- value) so the element styling uses utility classes instead of inline styles; update the JSX where descriptionText is rendered to remove fontSize from style and use Tailwind classes only.
🧹 Nitpick comments (1)
CHANGELOG.md (1)
20-20: Add PR reference for changelog consistency.Consider appending
(PR#128)to Line 20 to match the traceability style used by adjacent entries.Suggested doc tweak
-- **Font size setting** in Appearance settings — adjustable from 10px to 24px via dropdown, stored in `localStorage`, applied instantly via CSS custom property. All hardcoded `px` font sizes converted to `rem` units so the entire UI scales proportionally +- **Font size setting** in Appearance settings — adjustable from 10px to 24px via dropdown, stored in `localStorage`, applied instantly via CSS custom property. All hardcoded `px` font sizes converted to `rem` units so the entire UI scales proportionally (PR `#128`)🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@CHANGELOG.md` at line 20, Update the changelog entry that starts with "**Font size setting** in Appearance settings — adjustable from 10px to 24px via dropdown, stored in `localStorage`, applied instantly via CSS custom property. All hardcoded `px` font sizes converted to `rem` units so the entire UI scales proportionally" by appending " (PR `#128`)" to the end of that line so it matches the PR reference format used by adjacent entries.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@src/components/UpdateBadge.tsx`:
- Line 51: The rem values were calculated against a 16px root but your project
sets --font-size-base to 15px, so update the rem conversions in UpdateBadge
(className containing text-[0.5625rem]) and the other affected components
(StatusBar, TopBar, ContextMeter, InlineSelect, PanelErrorBoundary) to use 15px
as the base (e.g., replace text-[0.5625rem] with text-[0.6rem] for a 9px
target), or alternatively change the CSS root variable --font-size-base to 16px
if you intend to keep the existing rems; adjust only the rem numeric values or
the root variable so rendered pixel sizes match the intended design.
In `@src/contexts/SettingsContext.tsx`:
- Around line 113-117: The fontSize state accepts any number between 10–24 which
can produce values not present in the InlineSelect options and desync the
control; instead normalize to the discrete allowed sizes used by the UI. Create
an allowedSizes array (e.g. [10,12,14,16,18,20,22,24] or the exact options used
by InlineSelect), parse the saved localStorage value safely, then pick the
nearest allowedSizes entry (or fallback to the default 15) when initializing
fontSize in the useState initializer (fontSize, setFontSizeState) and likewise
normalize any updates that set fontSize (the setter/handler that currently
writes to localStorage and calls setFontSizeState) so only values from
allowedSizes are stored and emitted.
In `@src/index.css`:
- Around line 29-30: Add a blank line before the lone declarations causing
Stylelint's declaration-empty-line-before errors: insert an empty line
immediately above the "font-size: var(--font-size-base);" declaration and
likewise add an empty line before the other problematic declaration at the
bottom of the file (the one flagged on line 1227), so the declarations are
preceded by a blank line and satisfy the declaration-empty-line-before rule.
---
Outside diff comments:
In `@src/features/chat/components/ActivityLog.tsx`:
- Line 19: The container in ActivityLog is using a hard-coded pixel fontSize
('11px') which will desynchronize with the checkmark that uses rem; update the
inline style on the outer div (the element rendering fontFamily and fontSize) to
use rem units (e.g., fontSize: '0.6875rem') or remove the inline sizing and
replace with a responsive Tailwind utility so text scales with root font-size;
apply the same change to the other occurrence referenced around the row at the
other location (the second styled div on line ~35) to keep proportions
consistent.
In `@src/features/chat/components/ProcessingIndicator.tsx`:
- Around line 107-132: The inline hardcoded fontSize: '11px' in the
ProcessingIndicator component for the isRecovering and isStale blocks should be
replaced with Tailwind rem-based classes to respect font scaling; update the JSX
around isRecovering and isStale (the elements using recoveryReason and
secondsSinceEvent) to remove the inline fontSize style and add an appropriate
Tailwind utility class (e.g., text-xs or text-sm as needed) while keeping
existing classes like text-primary and text-orange and retaining paddingLeft via
existing className or convert to pl-8 to match the original spacing.
- Around line 79-85: In ProcessingIndicator, the inline style fontSize: '11px'
overrides the Tailwind text-[0.75rem] class and prevents rem scaling; remove the
inline fontSize (keep the Tailwind class) or replace it with a rem value, and
convert paddingLeft: '2rem' to a Tailwind padding class (e.g., pl-8 or an
appropriate pl- value) so the element styling uses utility classes instead of
inline styles; update the JSX where descriptionText is rendered to remove
fontSize from style and use Tailwind classes only.
---
Nitpick comments:
In `@CHANGELOG.md`:
- Line 20: Update the changelog entry that starts with "**Font size setting** in
Appearance settings — adjustable from 10px to 24px via dropdown, stored in
`localStorage`, applied instantly via CSS custom property. All hardcoded `px`
font sizes converted to `rem` units so the entire UI scales proportionally" by
appending " (PR `#128`)" to the end of that line so it matches the PR reference
format used by adjacent entries.
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 0bd67f1c-4d27-4ea2-a31c-531b2db50fda
⛔ Files ignored due to path filters (2)
docs/font-size-dropdown.pngis excluded by!**/*.pngdocs/font-size-setting.pngis excluded by!**/*.png
📒 Files selected for processing (62)
CHANGELOG.mdREADME.mddocs/ARCHITECTURE.mdsrc/components/ContextMeter.tsxsrc/components/PanelErrorBoundary.tsxsrc/components/StatusBar.tsxsrc/components/TopBar.tsxsrc/components/UpdateBadge.tsxsrc/components/ui/InlineSelect.tsxsrc/contexts/SettingsContext.tsxsrc/features/activity/AgentLog.tsxsrc/features/activity/EventLog.tsxsrc/features/auth/LoginPage.tsxsrc/features/charts/LightweightChart.tsxsrc/features/chat/ChatPanel.tsxsrc/features/chat/InputBar.tsxsrc/features/chat/MemoriesSection.tsxsrc/features/chat/MessageBubble.tsxsrc/features/chat/SearchBar.tsxsrc/features/chat/ToolCallBlock.tsxsrc/features/chat/components/ActivityLog.tsxsrc/features/chat/components/ChatHeader.tsxsrc/features/chat/components/ProcessingIndicator.tsxsrc/features/chat/components/ScrollToBottomButton.tsxsrc/features/chat/components/StreamingMessage.tsxsrc/features/chat/components/ToolGroupBlock.tsxsrc/features/command-palette/CommandPalette.tsxsrc/features/connect/ConnectDialog.tsxsrc/features/dashboard/MemoryList.tsxsrc/features/dashboard/TokenUsage.tsxsrc/features/file-browser/EditorTab.tsxsrc/features/file-browser/FileEditor.tsxsrc/features/file-browser/FileTreeNode.tsxsrc/features/file-browser/FileTreePanel.tsxsrc/features/kanban/CreateTaskDialog.tsxsrc/features/kanban/KanbanBoard.tsxsrc/features/kanban/KanbanCard.tsxsrc/features/kanban/KanbanColumn.tsxsrc/features/kanban/KanbanHeader.tsxsrc/features/kanban/KanbanQuickView.tsxsrc/features/kanban/ProposalInbox.tsxsrc/features/kanban/TaskDetailDrawer.tsxsrc/features/memory/AddMemoryDialog.tsxsrc/features/memory/ConfirmDeleteDialog.tsxsrc/features/memory/MemoryEditor.tsxsrc/features/memory/MemoryItem.tsxsrc/features/sessions/SessionInfoPanel.tsxsrc/features/sessions/SessionList.tsxsrc/features/sessions/SessionNode.tsxsrc/features/sessions/SpawnAgentDialog.tsxsrc/features/settings/AppearanceSettings.tsxsrc/features/settings/AudioSettings.tsxsrc/features/settings/ConnectionSettings.tsxsrc/features/settings/SettingsDrawer.tsxsrc/features/settings/VoicePhrasesModal.tsxsrc/features/workspace/WorkspacePanel.tsxsrc/features/workspace/WorkspaceTabs.tsxsrc/features/workspace/tabs/ConfigTab.tsxsrc/features/workspace/tabs/CronDialog.tsxsrc/features/workspace/tabs/CronsTab.tsxsrc/features/workspace/tabs/SkillsTab.tsxsrc/index.css
Add a user-configurable font size dropdown (10–24px) to the Appearance settings panel, letting users adjust the base UI text size. - Add --font-size-base CSS custom property on the html root element - Add fontSize state to SettingsContext with localStorage persistence - Add font size dropdown (InlineSelect) to AppearanceSettings - Convert all hardcoded px font-size values in index.css to rem units - Convert all text-[Npx] Tailwind classes across 57 components to rem equivalents so they scale with the root font size The preference is stored in localStorage under 'nerve:font-size' and defaults to 15px (matching the previous hardcoded value). Takes effect immediately without page reload. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
491a9ca to
a437d5b
Compare
|
@daggerhashimoto I corrected all the findings, but I'm not sure how to re-trigger coderabbitat. |
|
@CodeRabbit review |
✅ Actions performedReview triggered.
|
|
@CodeRabbit full review |
✅ Actions performedFull review triggered. |
|
Nice addition overall, this is a genuinely useful accessibility/comfort feature and the settings UX here is clean. Tested this locally. Looks good overall, but one thing is missing: the font size setting updates the app UI, but it does not affect the CodeMirror editor text. Can you wire the same setting through to the editor as well, so the editor content scales with the rest of the interface? |
|
Sure thing, but I haven't gotten to the CodeMirror area yet, where do I find it so I can check it myself. |
Add an independent font size selector for the CodeMirror editor, allowing users to scale the editor text separately from the UI. - Add editorFontSize / setEditorFontSize to SettingsContext with localStorage persistence under 'nerve:editor-font-size' (default 13px) - Add --editor-font-size CSS custom property on the html root element - Add Editor Font Size dropdown to AppearanceSettings using Code2 icon - Wire CodeMirror theme (editorTheme.ts) to use var(--editor-font-size) for the editor, search panel inputs, buttons, and labels - Add normalizeEditorFontSize helper with ALLOWED_EDITOR_FONT_SIZES set Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
|
Good catch — the CodeMirror editor was still using hardcoded Changes in the new commit (
All checks still pass (lint, build, 1245 tests). |
There was a problem hiding this comment.
🧹 Nitpick comments (2)
src/features/settings/AppearanceSettings.tsx (1)
13-41: Consider generating size option lists from one shared value array.Current duplicated option definitions increase maintenance overhead and can drift over time.
♻️ Suggested refactor
-const EDITOR_FONT_SIZE_OPTIONS = [ - { value: '10', label: '10px' }, - { value: '11', label: '11px' }, - { value: '12', label: '12px' }, - { value: '13', label: '13px (default)' }, - { value: '14', label: '14px' }, - { value: '15', label: '15px' }, - { value: '16', label: '16px' }, - { value: '17', label: '17px' }, - { value: '18', label: '18px' }, - { value: '20', label: '20px' }, - { value: '22', label: '22px' }, - { value: '24', label: '24px' }, -]; - -const FONT_SIZE_OPTIONS = [ - { value: '10', label: '10px' }, - { value: '11', label: '11px' }, - { value: '12', label: '12px' }, - { value: '13', label: '13px' }, - { value: '14', label: '14px' }, - { value: '15', label: '15px (default)' }, - { value: '16', label: '16px' }, - { value: '17', label: '17px' }, - { value: '18', label: '18px' }, - { value: '20', label: '20px' }, - { value: '22', label: '22px' }, - { value: '24', label: '24px' }, -]; +const FONT_SIZE_VALUES = [10, 11, 12, 13, 14, 15, 16, 17, 18, 20, 22, 24] as const; + +const toSizeOptions = (defaultValue: number) => + FONT_SIZE_VALUES.map((size) => ({ + value: String(size), + label: size === defaultValue ? `${size}px (default)` : `${size}px`, + })); + +const FONT_SIZE_OPTIONS = toSizeOptions(15); +const EDITOR_FONT_SIZE_OPTIONS = toSizeOptions(13);🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/features/settings/AppearanceSettings.tsx` around lines 13 - 41, Replace the duplicated EDITOR_FONT_SIZE_OPTIONS and FONT_SIZE_OPTIONS with a single source array of numeric size strings (e.g., FONT_SIZES = ['10','11',...,'24']) and derive both constants by mapping FONT_SIZES to { value, label } objects; when mapping, append " (default)" to the label for the size that should be default for each list (13 for EDITOR_FONT_SIZE_OPTIONS and 15 for FONT_SIZE_OPTIONS) so both EDITOR_FONT_SIZE_OPTIONS and FONT_SIZE_OPTIONS remain available but are generated from the shared FONT_SIZES to avoid drift.src/features/file-browser/editorTheme.ts (1)
17-17: Optional: de-duplicate repeated font-size token.The same
var(--editor-font-size, 13px)string is repeated several times; extracting a constant will reduce drift risk.♻️ Suggested refactor
import { EditorView } from '@codemirror/view'; import { HighlightStyle, syntaxHighlighting } from '@codemirror/language'; import { tags as t } from '@lezer/highlight'; +const EDITOR_FONT_SIZE = 'var(--editor-font-size, 13px)'; + export const nerveTheme = EditorView.theme( { '&': { backgroundColor: 'transparent', color: 'var(--foreground)', - fontSize: 'var(--editor-font-size, 13px)', + fontSize: EDITOR_FONT_SIZE, fontFamily: 'var(--font-mono)', height: '100%', }, @@ '.cm-panel.cm-search input': { - fontSize: 'var(--editor-font-size, 13px)', + fontSize: EDITOR_FONT_SIZE, @@ '.cm-panel.cm-search button': { - fontSize: 'var(--editor-font-size, 13px)', + fontSize: EDITOR_FONT_SIZE, @@ '.cm-panel.cm-search button[name="close"]': { - fontSize: 'var(--editor-font-size, 13px)', + fontSize: EDITOR_FONT_SIZE, @@ '.cm-panel.cm-search label': { - fontSize: 'var(--editor-font-size, 13px)', + fontSize: EDITOR_FONT_SIZE,Also applies to: 65-65, 73-73, 85-85, 90-90
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/features/file-browser/editorTheme.ts` at line 17, The repeated literal "var(--editor-font-size, 13px)" should be extracted to a single constant to avoid duplication; add a descriptive constant (e.g., EDITOR_FONT_SIZE or editorFontSizeToken) at the top of the module and replace each fontSize occurrence (the fontSize properties in the theme objects referenced in editorTheme.ts) with that constant so all instances (including the ones around lines noted) reference the single token.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Nitpick comments:
In `@src/features/file-browser/editorTheme.ts`:
- Line 17: The repeated literal "var(--editor-font-size, 13px)" should be
extracted to a single constant to avoid duplication; add a descriptive constant
(e.g., EDITOR_FONT_SIZE or editorFontSizeToken) at the top of the module and
replace each fontSize occurrence (the fontSize properties in the theme objects
referenced in editorTheme.ts) with that constant so all instances (including the
ones around lines noted) reference the single token.
In `@src/features/settings/AppearanceSettings.tsx`:
- Around line 13-41: Replace the duplicated EDITOR_FONT_SIZE_OPTIONS and
FONT_SIZE_OPTIONS with a single source array of numeric size strings (e.g.,
FONT_SIZES = ['10','11',...,'24']) and derive both constants by mapping
FONT_SIZES to { value, label } objects; when mapping, append " (default)" to the
label for the size that should be default for each list (13 for
EDITOR_FONT_SIZE_OPTIONS and 15 for FONT_SIZE_OPTIONS) so both
EDITOR_FONT_SIZE_OPTIONS and FONT_SIZE_OPTIONS remain available but are
generated from the shared FONT_SIZES to avoid drift.
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 0cc27a7f-5898-41c7-b814-6a4ccc415720
📒 Files selected for processing (3)
src/contexts/SettingsContext.tsxsrc/features/file-browser/editorTheme.tssrc/features/settings/AppearanceSettings.tsx
🚧 Files skipped from review as they are similar to previous changes (1)
- src/contexts/SettingsContext.tsx
Summary
Add a user-configurable font size dropdown (10–24px) to the Appearance settings panel. All UI text scales proportionally from a single CSS custom property on the document root.
Closes #127
Changes
fontSize/setFontSizestate, persisted tolocalStorageundernerve:font-size, default 15pxInlineSelectdropdown (10–24px) using theALargeSmalllucide icon--font-size-baseon<html>root, applied viauseEffectpxfont-size declarations toremunitstext-[Npx]Tailwind classes toremequivalents (e.g.,text-[12px]→text-[0.8rem])Verification
npm run lint— 0 errors (5 pre-existing warnings in upstream code)npm run build— passesnpm run build:server— passesnpm test -- --run— 1245 tests passed, 0 failuresAI Disclosure
This feature was developed with assistance from Claude Code (Claude Opus 4.6). All changes were reviewed, tested, and validated by the author.
Screenshots
Appearance settings with Font size selector:
Font size dropdown open (10px–24px):
Summary by CodeRabbit
New Features
Documentation