mirror of https://github.com/garrytan/gstack.git
Add a sidebar text-size selector to the terminal toolbar
The Side Panel terminal renders at a fixed 13px. This adds an xs/sm/md/lg/xl picker in the toolbar (A + dropdown, beside Restart) so users can size the text to their eyes. - sm = 13px is the unchanged default; the others step around it (xs 11, md 15, lg 17, xl 20). Nothing changes until you pick a size. - Persisted in chrome.storage.local, restored on load, applied to the live xterm. - Resize reflows correctly: xterm re-measures the character cell on the next render frame, so the change waits two animation frames before fitAddon.fit() and then sends the new cols/rows to the PTY. Fitting in the same tick reads the old cell and clips the grid until a close/reopen — this avoids that. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01GKj8Nr8T4GvryTcWBJRMyC
This commit is contained in:
parent
a3259400a3
commit
1316bd7c0c
|
|
@ -39,8 +39,18 @@
|
|||
ended: document.getElementById('terminal-ended'),
|
||||
restart: document.getElementById('terminal-restart'),
|
||||
restartNow: document.getElementById('terminal-restart-now'),
|
||||
fontSize: document.getElementById('terminal-fontsize'),
|
||||
};
|
||||
|
||||
// Sidebar text-size selector. sm = 13px is the shipped default (do not change it — it is
|
||||
// what every existing session renders at); the others step around it. Persisted per user
|
||||
// in chrome.storage.local and applied to the live xterm.
|
||||
const FONT_SIZES = { xs: 11, sm: 13, md: 15, lg: 17, xl: 20 };
|
||||
const FONT_SIZE_DEFAULT = 'sm';
|
||||
const FONT_SIZE_KEY = 'terminalFontSize';
|
||||
let fontSizeKey = FONT_SIZE_DEFAULT; // the chosen T-shirt size; px comes from FONT_SIZES
|
||||
const fontPx = () => FONT_SIZES[fontSizeKey] || FONT_SIZES[FONT_SIZE_DEFAULT];
|
||||
|
||||
/** State machine. */
|
||||
const STATE = {
|
||||
IDLE: 'idle',
|
||||
|
|
@ -392,7 +402,7 @@
|
|||
if (term) return;
|
||||
term = new Terminal({
|
||||
fontFamily: '"JetBrains Mono", "SF Mono", Menlo, "Noto Sans Mono CJK KR", "Malgun Gothic", monospace',
|
||||
fontSize: 13,
|
||||
fontSize: fontPx(), // the persisted size (default 13 = sm); see FONT_SIZES
|
||||
theme: { background: '#0a0a0a', foreground: '#e5e5e5' },
|
||||
cursorBlink: true,
|
||||
scrollback: 5000,
|
||||
|
|
@ -931,6 +941,40 @@
|
|||
els.restart?.addEventListener('click', forceRestart);
|
||||
els.restartNow?.addEventListener('click', forceRestart);
|
||||
|
||||
// Re-measure the terminal and tell the PTY its new size. Same body the first-fit and the
|
||||
// ResizeObserver use — a bare fitAddon.fit() is not enough: without the resize message
|
||||
// claude keeps wrapping to the old cols/rows.
|
||||
const refitTerminal = () => {
|
||||
try {
|
||||
fitAddon && fitAddon.fit();
|
||||
if (term && ws && ws.readyState === WebSocket.OPEN) {
|
||||
ws.send(JSON.stringify({ type: 'resize', cols: term.cols, rows: term.rows }));
|
||||
}
|
||||
} catch {}
|
||||
};
|
||||
|
||||
// Sidebar text-size selector: restore the saved size, then apply on change. Changing the
|
||||
// font is asynchronous inside xterm — it re-measures the character cell on the next render
|
||||
// frame, so fitting in the same tick reads the OLD cell and leaves the grid clipped (the
|
||||
// bug that made a live change need a close/reopen). Two rAFs let the new metrics land
|
||||
// before we fit + resize. If the terminal isn't up yet, ensureXterm reads fontPx() at
|
||||
// creation, so no refit is needed then.
|
||||
const applyFontSize = (key, persist) => {
|
||||
fontSizeKey = FONT_SIZES[key] ? key : FONT_SIZE_DEFAULT;
|
||||
if (els.fontSize) els.fontSize.value = fontSizeKey;
|
||||
if (term) {
|
||||
term.options.fontSize = fontPx();
|
||||
requestAnimationFrame(() => requestAnimationFrame(refitTerminal));
|
||||
}
|
||||
if (persist) { try { chrome.storage.local.set({ [FONT_SIZE_KEY]: fontSizeKey }); } catch {} }
|
||||
};
|
||||
els.fontSize?.addEventListener('change', (e) => applyFontSize(e.target.value, true));
|
||||
try {
|
||||
chrome.storage.local.get([FONT_SIZE_KEY], (r) => applyFontSize(r?.[FONT_SIZE_KEY] || FONT_SIZE_DEFAULT, false));
|
||||
} catch {
|
||||
applyFontSize(FONT_SIZE_DEFAULT, false);
|
||||
}
|
||||
|
||||
|
||||
// Live browser-tab state. background.js → sidepanel.js → us. We
|
||||
// forward over the live PTY WebSocket; terminal-agent.ts writes
|
||||
|
|
|
|||
|
|
@ -719,6 +719,38 @@ body::after {
|
|||
color: #f59e0b;
|
||||
border-color: #f59e0b;
|
||||
}
|
||||
/* Right cluster: text-size selector + Restart, kept together on the toolbar's right end. */
|
||||
.terminal-toolbar-right {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
.terminal-fontsize {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 3px;
|
||||
color: #a1a1aa;
|
||||
}
|
||||
/* The glyph is a size hint, not decoration — a small 'A' beside the picker. */
|
||||
.terminal-fontsize-icon {
|
||||
font-family: 'JetBrains Mono', monospace;
|
||||
font-size: 13px;
|
||||
line-height: 1;
|
||||
}
|
||||
.terminal-fontsize select {
|
||||
background: #0a0a0a;
|
||||
color: #a1a1aa;
|
||||
border: 1px solid #27272a;
|
||||
border-radius: 3px;
|
||||
padding: 3px 4px;
|
||||
font-size: 11px;
|
||||
font-family: 'JetBrains Mono', monospace;
|
||||
cursor: pointer;
|
||||
color-scheme: dark; /* keep the native option list dark, not a white flash over the panel */
|
||||
}
|
||||
.terminal-fontsize select:hover { color: #f59e0b; border-color: #f59e0b; }
|
||||
.terminal-fontsize select:focus-visible { outline: 2px solid #f59e0b; outline-offset: 1px; }
|
||||
.terminal-bootstrap {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
|
|
|
|||
|
|
@ -40,7 +40,19 @@
|
|||
<button id="chat-screenshot-btn" class="terminal-toolbar-btn" title="Take a screenshot">📸 Screenshot</button>
|
||||
<button id="chat-cookies-btn" class="terminal-toolbar-btn" title="Import cookies from your browser">🍪 Cookies</button>
|
||||
</div>
|
||||
<button class="terminal-toolbar-btn" id="terminal-restart-now" title="Restart Claude Code session">↻ Restart</button>
|
||||
<div class="terminal-toolbar-right">
|
||||
<label class="terminal-fontsize" title="Sidebar text size">
|
||||
<span class="terminal-fontsize-icon" aria-hidden="true">A</span>
|
||||
<select id="terminal-fontsize" aria-label="Sidebar text size">
|
||||
<option value="xs">XS</option>
|
||||
<option value="sm">SM</option>
|
||||
<option value="md">MD</option>
|
||||
<option value="lg">LG</option>
|
||||
<option value="xl">XL</option>
|
||||
</select>
|
||||
</label>
|
||||
<button class="terminal-toolbar-btn" id="terminal-restart-now" title="Restart Claude Code session">↻ Restart</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="terminal-bootstrap" id="terminal-bootstrap">
|
||||
<div class="terminal-bootstrap-icon">▸</div>
|
||||
|
|
|
|||
Loading…
Reference in New Issue