* feat(settings): add editor font size setting for chat input and code editor Adds an 'Editor font size' control in Settings > Appearance that sets an absolute px font size for the chat input textarea and the in-app CodeMirror editor. Mirrors the existing terminalFontSize lifecycle. - New store field editorFontSize (default 13, clamp 9-32, step 1) in useUIStore with narrow selectors at each consumer. - Persistence wired through appearanceAutoSave, desktop + runtime API types, and persistence.ts read/normalize. - Settings UI row (NumberInput) with reset to 13, VisibleSetting union entry, OpenChamberPage registration, and search index entry appearance.editor-font-size. - Applied as a post-zoom absolute override on the chat input textarea and on the CodeMirror theme's content rule, leaving gutter/line-number chrome at its existing hardcoded sizes (matches terminal scope). - All 10 locales translated (en, es, fr, ja, ko, pl, pt-BR, uk, zh-CN, zh-TW); no English placeholders in non-English dictionaries. Refs #1325 * fix(codemirror): use unitless lineHeight so it scales with editor font size The & rule in the CodeMirror theme set lineHeight to 1.5rem (~24px), which does not scale when editorFontSize is increased (e.g., 28-32px). This causes overlapping lines at larger font sizes. Change to unitless 1.5, which scales proportionally with whatever fontSize resolves to (dynamic prop or --text-code fallback). Matches browser best practice for proportional leading. Review comment: https://github.com/openchamber/openchamber/pull/2065 --------- Co-authored-by: bashrusakh <bashrusakh@users.noreply.github.com> Co-authored-by: Bohdan Triapitsyn <artmore@protonmail.com>
This commit is contained in:
committed by
GitHub
co-authored by
bashrusakh
Bohdan Triapitsyn
parent
bfaf62e222
commit
e0229917f8
@@ -2885,17 +2885,19 @@ export const FilesView: React.FC<FilesViewProps> = ({ mode = 'full' }) => {
|
||||
return () => window.removeEventListener('keydown', handleKeyDown);
|
||||
}, [canEdit, isMobile, shortcutOverrides, textViewMode]);
|
||||
|
||||
const editorFontSize = useUIStore((state) => state.editorFontSize);
|
||||
|
||||
const editorExtensions = React.useMemo(() => {
|
||||
if (!selectedFile?.path) {
|
||||
return [createFlexokiCodeMirrorTheme(currentTheme)];
|
||||
return [createFlexokiCodeMirrorTheme(currentTheme, { fontSize: editorFontSize })];
|
||||
}
|
||||
|
||||
// Shiki token colors (worker-backed) match the Shiki file view exactly.
|
||||
// Same language resolver as the view, so both agree on the language. When
|
||||
// Shiki is the color source, drop the lezer token colors to avoid a
|
||||
// competing highlighter (keep the lezer language for indentation/folding).
|
||||
// competing highlighter (Keep the lezer language for indentation/folding).
|
||||
const shikiLanguage = getLanguageFromExtension(selectedFile.path);
|
||||
const extensions = [createFlexokiCodeMirrorTheme(currentTheme, shikiLanguage ? { syntaxColors: false } : undefined)];
|
||||
const extensions = [createFlexokiCodeMirrorTheme(currentTheme, shikiLanguage ? { syntaxColors: false, fontSize: editorFontSize } : { fontSize: editorFontSize })];
|
||||
const language = staticLanguageExtension ?? dynamicLanguageExtension;
|
||||
if (language) {
|
||||
extensions.push(language);
|
||||
@@ -2925,7 +2927,7 @@ export const FilesView: React.FC<FilesViewProps> = ({ mode = 'full' }) => {
|
||||
}));
|
||||
}
|
||||
return extensions;
|
||||
}, [currentTheme, selectedFile?.path, staticLanguageExtension, dynamicLanguageExtension, wrapLines, isMobile, nudgeEditorSelectionAboveKeyboard]);
|
||||
}, [currentTheme, selectedFile?.path, staticLanguageExtension, dynamicLanguageExtension, wrapLines, isMobile, nudgeEditorSelectionAboveKeyboard, editorFontSize]);
|
||||
|
||||
const pierreTheme = React.useMemo(
|
||||
() => ({ light: lightTheme.metadata.id, dark: darkTheme.metadata.id }),
|
||||
|
||||
@@ -345,12 +345,14 @@ export const PlanView: React.FC<PlanViewProps> = ({ targetPath = null }) => {
|
||||
};
|
||||
}, [cancel, commentText, editingDraftId, isMobile, lineSelection]);
|
||||
|
||||
const editorFontSize = useUIStore((state) => state.editorFontSize);
|
||||
|
||||
const editorExtensions = React.useMemo(() => {
|
||||
// Shiki token colors only for code files; markdown keeps the lezer
|
||||
// highlighter (markdown-aware bold headings etc., and no Shiki view to match).
|
||||
const shikiLanguage = resolvedPath ? getLanguageFromExtension(resolvedPath) : null;
|
||||
const useShiki = Boolean(shikiLanguage) && shikiLanguage !== 'markdown';
|
||||
const extensions = [createFlexokiCodeMirrorTheme(currentTheme, useShiki ? { syntaxColors: false } : undefined)];
|
||||
const extensions = [createFlexokiCodeMirrorTheme(currentTheme, useShiki ? { syntaxColors: false, fontSize: editorFontSize } : { fontSize: editorFontSize })];
|
||||
const language = languageByExtension(resolvedPath || 'plan.md');
|
||||
if (language) {
|
||||
extensions.push(language);
|
||||
@@ -364,7 +366,7 @@ export const PlanView: React.FC<PlanViewProps> = ({ targetPath = null }) => {
|
||||
}
|
||||
extensions.push(EditorView.lineWrapping);
|
||||
return extensions;
|
||||
}, [currentTheme, resolvedPath]);
|
||||
}, [currentTheme, resolvedPath, editorFontSize]);
|
||||
|
||||
React.useEffect(() => {
|
||||
// Saved project plans opened via context panel should work even when session plan mode is off.
|
||||
|
||||
Reference in New Issue
Block a user