diff --git a/packages/review-editor/App.tsx b/packages/review-editor/App.tsx index 48f3c2c44..3b43b7a39 100644 --- a/packages/review-editor/App.tsx +++ b/packages/review-editor/App.tsx @@ -153,6 +153,7 @@ const ReviewApp: React.FC = () => { const diffHideWhitespace = useConfigValue('diffHideWhitespace'); const diffFontFamily = useConfigValue('diffFontFamily'); const diffFontSize = useConfigValue('diffFontSize'); + const diffTabSize = useConfigValue('diffTabSize'); // Load custom diff font and override --font-mono for surrounding review elements useEffect(() => { @@ -167,7 +168,8 @@ const ReviewApp: React.FC = () => { } else { document.documentElement.style.removeProperty('--diff-font-size-override'); } - }, [diffFontFamily, diffFontSize]); + document.documentElement.style.setProperty('--diffs-tab-size', String(diffTabSize)); + }, [diffFontFamily, diffFontSize, diffTabSize]); const reviewSidebar = useSidebar(true, 'annotations'); const [isFileTreeOpen, setIsFileTreeOpen] = useState(true); diff --git a/packages/review-editor/components/DiffOptionsPopover.tsx b/packages/review-editor/components/DiffOptionsPopover.tsx index 12c884250..f7711b2e1 100644 --- a/packages/review-editor/components/DiffOptionsPopover.tsx +++ b/packages/review-editor/components/DiffOptionsPopover.tsx @@ -32,6 +32,36 @@ function CompactSegmented({ options, value, onChange }: { ); } +function CompactStepper({ value, min, max, onChange, label }: { + value: number; + min: number; + max: number; + onChange: (v: number) => void; + label: string; +}) { + const clamp = (n: number) => Math.max(min, Math.min(max, n)); + return ( +
+ {label} +
+ + {value} + +
+
+ ); +} + function CompactToggle({ checked, onChange, label }: { checked: boolean; onChange: (v: boolean) => void; @@ -64,6 +94,7 @@ export const DiffOptionsPopover: React.FC = () => { const diffShowLineNumbers = useConfigValue('diffShowLineNumbers'); const diffShowBackground = useConfigValue('diffShowBackground'); const diffHideWhitespace = useConfigValue('diffHideWhitespace'); + const diffTabSize = useConfigValue('diffTabSize'); return ( @@ -114,6 +145,13 @@ export const DiffOptionsPopover: React.FC = () => { configStore.set('diffShowLineNumbers', v)} label="Line numbers" /> configStore.set('diffShowBackground', v)} label="Diff background" /> configStore.set('diffHideWhitespace', v)} label="Hide whitespace" /> + configStore.set('diffTabSize', v)} + /> diff --git a/packages/shared/config.ts b/packages/shared/config.ts index 494a95ced..adc290bca 100644 --- a/packages/shared/config.ts +++ b/packages/shared/config.ts @@ -21,6 +21,7 @@ export interface DiffOptions { showDiffBackground?: boolean; fontFamily?: string; fontSize?: string; + tabSize?: number; hideWhitespace?: boolean; defaultDiffType?: DefaultDiffType; } diff --git a/packages/ui/config/settings.ts b/packages/ui/config/settings.ts index 4739c7d97..18d1a8d3e 100644 --- a/packages/ui/config/settings.ts +++ b/packages/ui/config/settings.ts @@ -180,6 +180,21 @@ export const SETTINGS = { }, toServer: (v: string) => ({ diffOptions: { fontSize: v } }), }, + diffTabSize: { + defaultValue: 2 as number, + fromCookie: () => { + const v = storage.getItem('plannotator-diff-tab-size'); + const n = v ? parseInt(v, 10) : NaN; + return Number.isFinite(n) && n >= 1 && n <= 8 ? n : undefined; + }, + toCookie: (v: number) => storage.setItem('plannotator-diff-tab-size', String(v)), + serverKey: 'diffOptions', + fromServer: (sc: Record) => { + const v = (sc.diffOptions as Record | undefined)?.tabSize; + return typeof v === 'number' && v >= 1 && v <= 8 ? v : undefined; + }, + toServer: (v: number) => ({ diffOptions: { tabSize: v } }), + }, conventionalComments: { defaultValue: false as boolean, fromCookie: () => {