feat(ui): add ctrl +/-/0 shortcuts for terminal font size - #6937
Merged
Conversation
The web terminal could only change its font size through the settings drawer, which means a mouse round-trip in the middle of a keyboard-driven task. Every native terminal binds ctrl +/- for this, so the muscle memory was already there but did nothing useful: the browser claimed the keystroke and zoomed the whole console UI instead. The terminal now handles those keys itself while focused. Ctrl +/- steps the size by one within the existing 8-24 range and ctrl 0 returns it to the default, with cmd covering macOS. The keystroke is withheld from both the browser and the remote shell, so the page no longer zooms and no stray character reaches the command line. Nothing new holds the size. The shortcut reuses the store action the settings drawer already calls, so the two can never disagree and the choice still survives a reload. The bounds and the default move into exported constants now that a third caller needs them. Restoring a persisted size also parses defensively, fixing a corrupt localStorage value being accepted as NaN and an out-of-range one being applied unclamped.
luizhf42
approved these changes
Aug 21, 2026
Member
|
/review |
Code Review CompleteThe automated review ran but did not post an updated summary — this usually means no new issues were found since the previous review. If you've pushed changes and want a fresh pass, comment |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
While a terminal is focused,
Ctrl+andCtrl-step the terminal font size by one within the existing 8-24 range, andCtrl0returns it to the default.Cmdsubstitutes forCtrlon macOS. The keystroke is withheld from both the browser and the remote shell, so the page no longer zooms and no stray character lands on the command line.Closes: #6936
Why
Changing the font size previously meant opening the settings drawer and clicking its
+/-buttons, which is a mouse round-trip in the middle of a keyboard-driven task. Every native terminal binds these keys for this, so the muscle memory was already there but did nothing useful: the browser claimed the keystroke and zoomed the whole console UI instead of the terminal text.The shortcut deliberately reuses the size that already exists rather than introducing a second one, so the drawer and the keyboard can never disagree and the choice keeps surviving reloads for free.
Changes
fontSizeShortcut.ts: a purenextFontSize(current, event)that maps a keystroke to the size it asks for, ornull. Keeping the step arithmetic behind this seam is what makes the whole behaviour unit-testable without constructing xterm.TerminalInstance.tsx: registers the handler via xterm'sattachCustomKeyEventHandler, which is the seam that can withhold a key from the remote shell. It guards onkeydown(the handler also fires forkeyup), callspreventDefault()to suppress browser zoom, and reads the current size from the store rather than a render-time binding, since the handler is registered once and would otherwise always step from the size the terminal was created with.terminalThemeStore.ts: bounds and default extracted into exported constants now that a third caller needs them. Restoring a persisted size now parses defensively.TerminalSettingsDrawer.tsx: consumes those constants instead of repeating8and24.Two incidental fixes fell out of testing the store: a corrupt
localStoragevalue was accepted asNaNand became the font size, and a persisted out-of-range value was applied unclamped.Ctrl_is deliberately not bound.-needs no Shift, so accepting it would buy nothing and would steal0x1F(readline/emacs undo) from the remote shell.Testing
Unit tests cover the two seams the behaviour actually lives at - 36 tests across
nextFontSizeand the store. The mapping is table-driven over+,=,-,0, numpad, both modifiers, no modifier,Altheld, and unrelated keys.These do not prove the feature works, only that the logic is right. Rendering xterm under jsdom was rejected (it needs a real canvas), so the wiring and the resize round-trip were exercised by hand in the running stack:
ssh root@dev.agent@localhostCtrl-/Ctrl+- terminal text resizes, console chrome (sidebar, tabs, taskbar) does not, confirming browser zoom is suppressed-or+character appears on the command line, confirming the key is withheld from the shellhtop, resize, and confirm it redraws correctly rather than corrupting - this is what proves the resize frame reached the PTY and the remote program got its SIGWINCHCtrl0snaps back to the defaultKnown limitation
Holding the key is not as fluid as a native terminal. Each step reflows the scrollback, resizes the remote PTY and writes a recorder event, and that cost is per-step. An accelerating step was tried and reverted - it traded the slowness for visible jumpiness, which felt worse. Making it genuinely smooth needs a profile to establish which reflow dominates, so it is left alone here rather than tuned blind.