Skip to content

Conversation

@maunguyengit
Copy link

@maunguyengit maunguyengit commented Sep 2, 2025

🎯 Feature Overview

This PR adds a font size adjustment setting in Settings → Editor → General to improve readability and accessibility.

✨ What's New

  • Font Size Slider: Adjustable range from 12px to 24px (default: 16px)
  • Real-time Updates: Changes apply immediately without page reload
  • Persistent Settings: Font size saves across app restarts
  • Accessibility: Improves readability for users who need larger text

🔧 Implementation Details

  • Added fontSize field to EditorSettingSchema
  • Created FontSizeSettings component with slider control
  • Integrated with existing theme system via CSS variables (--affine-font-base)
  • Added internationalization support
  • Follows AFFiNE's design patterns and coding standards

🧪 Testing

  • Font size changes work in real-time
  • Settings persist across app restarts
  • UI integrates seamlessly with existing settings
  • No breaking changes to existing functionality

📸 Screenshots

(You can add screenshots of the font size slider in action)

Addresses user requests for customizable font sizes to improve the AFFiNE user experience.

Summary by CodeRabbit

  • New Features

    • Added a Font size control in Editor settings with a slider (12–24) and live preview of the current value.
    • Changes apply instantly across the app and persist, including compatibility with custom themes.
    • Font size is applied on initial load to ensure consistent appearance.
  • Localization

    • Added English labels and description for the new Font size setting.
@CLAassistant
Copy link

CLAassistant commented Sep 2, 2025

CLA assistant check
All committers have signed the CLA.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Sep 2, 2025

Walkthrough

Adds a new editor font-size setting (12–24, default 16) with a slider UI, persists it via EditorSettingService, and applies it by updating the --affine-font-base CSS variable on mount and when changed. Integrates settings into the custom theme page and adds English i18n strings.

Changes

Cohort / File(s) Summary
Editor Settings UI
packages/frontend/core/src/desktop/dialogs/setting/general-setting/editor/general.tsx, packages/frontend/core/src/desktop/dialogs/setting/general-setting/editor/style.css.ts
Introduces FontSizeSettings component with Slider (12–24, step 1), syncs value from settings and writes to CSS var --affine-font-base. Adds styles: fontSizeContainer, fontSizeSlider, fontSizeValue.
Editor Setting Schema
packages/frontend/core/src/modules/editor-setting/schema.ts
Adds fontSize: z.number().min(12).max(24).default(16) to AffineEditorSettingSchema; EditorSettingSchema now includes fontSize.
Custom Theme Listener
packages/frontend/core/src/desktop/pages/root/custom-theme/index.tsx
Subscribes to EditorSettingService.settings$ and updates document root CSS var --affine-font-base on fontSize changes.
i18n resources
packages/frontend/i18n/src/resources/en.json
Adds English keys: com.affine.settings.editorSettings.general.font-size.title and .description.

Sequence Diagram(s)

sequenceDiagram
  participant U as User
  participant UI as Settings UI (General)
  participant S as EditorSettingService
  participant DOM as Document Root (CSS vars)
  participant T as CustomThemeModifier

  U->>UI: Adjust font size (Slider)
  UI->>S: set({ fontSize })
  Note right of S: settings$ emits updated state
  S-->>UI: settings$ (fontSize)
  UI->>DOM: set --affine-font-base = fontSize + "px"
  S-->>T: settings$ (fontSize)
  T->>DOM: set --affine-font-base = fontSize + "px"
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Suggested labels

mod:i18n, app:core

Suggested reviewers

  • CatsJuice
  • Saul-Mirone

Poem

I nibble on pixels, hop-slide with delight,
A slider of sizes, from noon into night.
New fonts bloom larger—so crisp, so precise—
I twirl my whiskers, adjust it just right.
With themes and settings dancing in place,
--affine-font-base puts a smile on my face. 🐇✨

✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • 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
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

CodeRabbit Commands (Invoked using PR/Issue comments)

Type @coderabbitai help to get the list of available commands.

Other keywords and placeholders

  • Add @coderabbitai ignore or @coderabbit ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Status, Documentation and Community

  • Visit our Status Page to check the current availability of CodeRabbit.
  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.
@github-actions github-actions bot added mod:i18n Related to i18n app:core labels Sep 2, 2025
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
packages/frontend/core/src/desktop/pages/root/custom-theme/index.tsx (1)

28-43: Prevent theme updates from wiping --affine-font-base.

document.documentElement.style.cssText = '' clears all inline vars, so switching themes can drop the font-size until the setting changes again. Re-apply the var inside the theme subscription and include settings.fontSize in the effect deps. Also avoid the truthy guard so future 0 values won’t be skipped.

Apply:

   const sub = themeEditorService.customTheme$.subscribe(themeObj => {
     if (!themeObj) return;

     const mode = resolvedTheme === 'dark' ? 'dark' : 'light';
     const valueMap = themeObj[mode];

     // remove previous style
     // TOOD(@CatsJuice): find better way to remove previous style
     document.documentElement.style.cssText = '';
     // recover color scheme set by next-themes
     document.documentElement.style.colorScheme = mode;

     Object.entries(valueMap).forEach(([key, value]) => {
       value && document.documentElement.style.setProperty(key, value);
     });
+    // keep editor base font size after clearing cssText
+    document.documentElement.style.setProperty(
+      '--affine-font-base',
+      `${settings.fontSize}px`
+    );
   });
@@
-}, [resolvedTheme, enableThemeEditor, themeEditorService]);
+}, [resolvedTheme, enableThemeEditor, themeEditorService, settings.fontSize]);
@@
-  useEffect(() => {
-    if (settings.fontSize) {
-      document.documentElement.style.setProperty('--affine-font-base', `${settings.fontSize}px`);
-    }
-  }, [settings.fontSize]);
+  useEffect(() => {
+    document.documentElement.style.setProperty(
+      '--affine-font-base',
+      `${settings.fontSize}px`
+    );
+  }, [settings.fontSize]);

Also applies to: 49-49, 51-56

🧹 Nitpick comments (3)
packages/frontend/core/src/modules/editor-setting/schema.ts (1)

22-22: Constrain to integers and accept coerced input.

Avoid accidental decimals and tolerate stringified values from storage/imports.

-  fontSize: z.number().min(12).max(24).default(16),
+  fontSize: z.coerce.number().int().min(12).max(24).default(16),
packages/frontend/core/src/desktop/dialogs/setting/general-setting/editor/style.css.ts (1)

167-183: Make slider row fluid to avoid cramped layouts.

Using a fixed 250px width may clip on narrower containers. Prefer 100% with a max.

 export const fontSizeContainer = style({
   display: 'flex',
   alignItems: 'center',
   gap: '12px',
-  width: '250px',
+  width: '100%',
+  maxWidth: '250px',
 });
packages/frontend/core/src/desktop/dialogs/setting/general-setting/editor/general.tsx (1)

312-351: Persist on commit; update CSS live to reduce writes.

Write to settings on slider commit (or throttled) to avoid persisting every pixel change. Keep live CSS updates for instant feedback.

Verify Slider exposes onValueCommit (Radix-compatible). If yes:

-  const onFontSizeChange = useCallback(
-    (fontSize: number[]) => {
-      const size = fontSize[0];
-      editorSettingService.editorSetting.set('fontSize', size);
-      // Update CSS variable immediately
-      document.documentElement.style.setProperty('--affine-font-base', `${size}px`);
-    },
-    [editorSettingService.editorSetting]
-  );
+  const onFontSizeChange = useCallback((fontSize: number[]) => {
+    const size = fontSize[0];
+    // live preview only
+    document.documentElement.style.setProperty('--affine-font-base', `${size}px`);
+  }, []);
+
+  const onFontSizeCommit = useCallback(
+    (fontSize: number[]) => {
+      const size = fontSize[0];
+      editorSettingService.editorSetting.set('fontSize', size);
+    },
+    [editorSettingService.editorSetting]
+  );
@@
         <Slider
           value={[settings.fontSize]}
-          onValueChange={onFontSizeChange}
+          onValueChange={onFontSizeChange}
+          onValueCommit={onFontSizeCommit}
           min={12}
           max={24}
           step={1}
           className={styles.fontSizeSlider}
         />

If not supported, consider debouncing set('fontSize') with setTimeout (~150ms).

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 18faaa3 and 0233fa8.

📒 Files selected for processing (5)
  • packages/frontend/core/src/desktop/dialogs/setting/general-setting/editor/general.tsx (3 hunks)
  • packages/frontend/core/src/desktop/dialogs/setting/general-setting/editor/style.css.ts (1 hunks)
  • packages/frontend/core/src/desktop/pages/root/custom-theme/index.tsx (3 hunks)
  • packages/frontend/core/src/modules/editor-setting/schema.ts (1 hunks)
  • packages/frontend/i18n/src/resources/en.json (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (2)
packages/frontend/core/src/desktop/dialogs/setting/general-setting/editor/general.tsx (3)
packages/common/infra/src/framework/react/index.tsx (1)
  • useServices (29-45)
packages/frontend/core/src/components/properties/table.css.ts (1)
  • fontSize (6-6)
packages/frontend/component/src/components/setting-components/setting-row.tsx (1)
  • SettingRow (17-49)
packages/frontend/core/src/desktop/pages/root/custom-theme/index.tsx (1)
packages/common/infra/src/framework/react/index.tsx (1)
  • useServices (29-45)
🔇 Additional comments (4)
packages/frontend/core/src/desktop/pages/root/custom-theme/index.tsx (1)

2-2: LGTM: service wiring and settings subscription look correct.

Also applies to: 11-15, 19-19

packages/frontend/i18n/src/resources/en.json (1)

1329-1331: LGTM: new i18n keys read well and match existing tone.

packages/frontend/core/src/desktop/dialogs/setting/general-setting/editor/general.tsx (2)

12-12: LGTM: Slider import.


566-566: LGTM: placement in General settings is consistent with existing rows.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

app:core mod:i18n Related to i18n

2 participants