feat(editor): add font size adjustment in editor settings (#13549)

Co-authored-by: DarkSky <25152247+darkskygit@users.noreply.github.com>
Co-authored-by: DarkSky <darksky2048@gmail.com>
This commit is contained in:
Mau Nguyen
2025-11-15 07:57:17 -08:00
committed by GitHub
parent d90eeffe84
commit 71d682c1c0
7 changed files with 83 additions and 2 deletions

View File

@@ -9,6 +9,7 @@ import {
type RadioItem,
RowInput,
Scrollable,
Slider,
Switch,
useConfirmModal,
} from '@affine/component';
@@ -308,6 +309,46 @@ const CustomFontFamilySettings = () => {
);
};
const FontSizeSettings = () => {
const t = useI18n();
const { editorSettingService } = useServices({ EditorSettingService });
const settings = useLiveData(editorSettingService.editorSetting.settings$);
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]
);
// Apply current font size to CSS variable on mount
useEffect(() => {
document.documentElement.style.setProperty('--affine-font-base', `${settings.fontSize}px`);
}, [settings.fontSize]);
return (
<SettingRow
name={t['com.affine.settings.editorSettings.general.font-size.title']()}
desc={t['com.affine.settings.editorSettings.general.font-size.description']()}
>
<div className={styles.fontSizeContainer}>
<Slider
value={[settings.fontSize]}
onValueChange={onFontSizeChange}
min={12}
max={24}
step={1}
className={styles.fontSizeSlider}
/>
<span className={styles.fontSizeValue}>{settings.fontSize}px</span>
</div>
</SettingRow>
);
};
const menuContentOptions: MenuProps['contentOptions'] = {
align: 'end',
sideOffset: 16,
@@ -522,6 +563,7 @@ export const General = () => {
<AISettings />
<FontFamilySettings />
<CustomFontFamilySettings />
<FontSizeSettings />
<NewDocDefaultModeSettings />
{BUILD_CONFIG.isElectron && <SpellCheckSettings />}
{environment.isLinux && <MiddleClickPasteSettings />}

View File

@@ -163,3 +163,21 @@ export const spellCheckSettingDescriptionButton = style({
color: cssVarV2('text/link'),
fontSize: 'inherit',
});
export const fontSizeContainer = style({
display: 'flex',
alignItems: 'center',
gap: '12px',
width: '250px',
});
export const fontSizeSlider = style({
flex: 1,
});
export const fontSizeValue = style({
fontSize: cssVar('fontSm'),
color: cssVarV2('text/secondary'),
minWidth: '40px',
textAlign: 'right',
});

View File

@@ -1,4 +1,5 @@
import { FeatureFlagService } from '@affine/core/modules/feature-flag';
import { EditorSettingService } from '@affine/core/modules/editor-setting';
import { ThemeEditorService } from '@affine/core/modules/theme-editor';
import { useLiveData, useServices } from '@toeverything/infra';
import { useTheme } from 'next-themes';
@@ -7,13 +8,15 @@ import { useEffect } from 'react';
let _provided = false;
export const CustomThemeModifier = () => {
const { themeEditorService, featureFlagService } = useServices({
const { themeEditorService, featureFlagService, editorSettingService } = useServices({
ThemeEditorService,
FeatureFlagService,
EditorSettingService,
});
const enableThemeEditor = useLiveData(
featureFlagService.flags.enable_theme_editor.$
);
const settings = useLiveData(editorSettingService.editorSetting.settings$);
const { resolvedTheme } = useTheme();
useEffect(() => {
@@ -45,5 +48,12 @@ export const CustomThemeModifier = () => {
};
}, [resolvedTheme, enableThemeEditor, themeEditorService]);
// Apply font size CSS variable when settings change
useEffect(() => {
if (settings.fontSize) {
document.documentElement.style.setProperty('--affine-font-base', `${settings.fontSize}px`);
}
}, [settings.fontSize]);
return null;
};

View File

@@ -19,6 +19,7 @@ export const fontStyleOptions = [
const AffineEditorSettingSchema = z.object({
fontFamily: z.enum(['Sans', 'Serif', 'Mono', 'Custom']).default('Sans'),
customFontFamily: z.string().default(''),
fontSize: z.number().min(12).max(24).default(16),
newDocDefaultMode: z.enum(['edgeless', 'page', 'ask']).default('page'),
fullWidthLayout: z.boolean().default(false),
displayDocInfo: z.boolean().default(true),