Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 17 additions & 3 deletions src/ui/tui.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -64,14 +64,28 @@ const SPINNER_FRAMES = ["⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧",
/** Track terminal columns reactively so resize triggers a re-render. */
function useTerminalColumns(): number {
const { stdout } = useStdout();
const accessible = useIsScreenReaderEnabled();
const [columns, setColumns] = useState(stdout.columns ?? 80);
useEffect(() => {
const onResize = () => setColumns(stdout.columns ?? 80);
stdout.on("resize", onResize);
const onResize = () => {
// Terminal reflow on resize invalidates Ink's line-position tracking,
// causing ghost artifacts ("screen cheese"). We use prependListener so
// this fires BEFORE Ink's own resize handler, clearing the screen
// before Ink re-renders — avoiding a wasted double-paint.
// Skip in accessible mode to avoid screen readers announcing escape noise.
if (!accessible) {
stdout.write("\x1b[2J\x1b[H");
}
setColumns(stdout.columns ?? 80);
};
// prependListener ensures our clear runs before Ink's resized() handler,
// which only clears on width decrease. This covers width increase and
// height-only changes where Ink's log-update state goes stale.
stdout.prependListener("resize", onResize);
return () => {
stdout.off("resize", onResize);
};
}, [stdout]);
}, [stdout, accessible]);
return columns;
}

Expand Down
Loading