Per-pane and global terminal zoom via keyboard

Each leaf now carries an optional fontSizeOffset, persisted in
workspace.json alongside everything else. Ctrl+= / Ctrl+- / Ctrl+0
adjust the active pane; adding Shift escalates to every pane (the
mirror of the broadcast Shift+Alt convention, with shift alone since
the keys are otherwise unused). Bindings match on e.code so layouts
that don't have "=" / "-" / "0" in the same spot still work.

XtermPane gained a fontSize prop. A secondary effect reacts to changes:
set term.options.fontSize, fit() to recompute cols/rows for the new
cell size, refresh(), then resizePane so bash redraws the prompt at
the right width. No remount, so PTY + scrollback survive zoom changes.

The new tree helpers (resolveFontSize / adjustFontSize /
adjustAllFontSizes) are metadata-only — they don't swap leaf ids, so
nothing respawns. reshapeToPreset also carries the offset across when
splicing existing leaves into a new layout. 12 new vitest cases pin
those invariants plus the clamp and reset-to-default behaviour.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
megaproxy 2026-05-22 22:48:35 +01:00
parent 8f9667b218
commit aab36afce4
6 changed files with 237 additions and 11 deletions

View file

@ -22,6 +22,8 @@ import {
changeLabel,
toggleBroadcast as toggleBroadcastInTree,
setAllBroadcast,
adjustFontSize,
adjustAllFontSizes,
reshapeToPreset,
flattenLayout,
updateSplitRatio,
@ -278,6 +280,23 @@ export default function App() {
return;
}
// Ctrl[+Shift]+= / - / 0 — terminal font size. Browser convention:
// unshifted touches the active pane, Shift escalates to every pane.
// Match on e.code so the bindings work the same across layouts (and
// regardless of whether Shift turns "=" into "+" etc.).
if (ctrl && !alt && (e.code === "Equal" || e.code === "Minus" || e.code === "Digit0")) {
e.preventDefault();
e.stopPropagation();
const delta =
e.code === "Equal" ? 1 : e.code === "Minus" ? -1 : null;
if (shift) {
setTree((t) => adjustAllFontSizes(t, delta));
} else if (activeLeafId) {
setTree((t) => adjustFontSize(t, activeLeafId, delta));
}
return;
}
// All remaining shortcuts require Ctrl+Shift with no Alt.
if (!ctrl || !shift || alt) return;