fix(terminal): refit after fonts load

This commit is contained in:
Gabriel Brown
2026-07-10 17:06:33 -04:00
parent 0b5a2c0411
commit 75d06394ce
4 changed files with 114 additions and 10 deletions
@@ -0,0 +1,21 @@
export const scheduleTerminalFits = (deps: {
fit: () => void;
sendResize: () => void;
fontsReady: Promise<unknown>;
loadNerdFont: () => Promise<unknown>;
raf: (cb: () => void) => void;
isAborted: () => boolean;
}): void => {
const refit = () => {
if (deps.isAborted()) return;
deps.fit();
deps.sendResize();
};
deps.raf(refit);
void deps.fontsReady.then(refit).catch(() => undefined);
void deps
.loadNerdFont()
.then(refit)
.catch(() => undefined);
};
@@ -6,6 +6,8 @@ import { useTheme } from 'next-themes';
import { Button } from '@spoon/ui';
import { scheduleTerminalFits } from './terminal-fit';
import '@xterm/xterm/css/xterm.css';
const TERMINAL_FONT =
@@ -143,18 +145,8 @@ export const WorkspaceTerminal = ({
term.loadAddon(fit);
term.loadAddon(new WebLinksAddon());
term.open(container);
fit.fit();
termRef.current = term;
// Pull in the Nerd Font icon glyphs (loaded lazily by unicode-range) and
// repaint once ready so powerline/oh-my-posh/eza icons render.
void document.fonts
.load("16px 'Symbols Nerd Font Mono'", '\ue0b0')
.then(() => {
if (!isAborted()) term.refresh(0, term.rows - 1);
})
.catch(() => undefined);
const sendResize = () => {
if (ws?.readyState !== WebSocket.OPEN) return;
ws.send(
@@ -162,6 +154,26 @@ export const WorkspaceTerminal = ({
);
};
scheduleTerminalFits({
fit: () => {
try {
fit.fit();
} catch {
// ignore transient layout errors
}
},
sendResize,
fontsReady: document.fonts.ready,
loadNerdFont: () =>
document.fonts
.load("16px 'Symbols Nerd Font Mono'", '\ue0b0')
.then(() => {
if (!isAborted()) term.refresh(0, term.rows - 1);
}),
raf: (cb) => requestAnimationFrame(cb),
isAborted,
});
ws = new WebSocket(url);
ws.binaryType = 'arraybuffer';
ws.onopen = () => {