Skip to content

Commit ce0b509

Browse files
digitaraldHarald KirschnerCopilot
authored
fix(ui): prevent terminal screen cheese on TUI resize (#76)
* fix(ui): improve terminal resize handling to prevent rendering artifacts * fix(ui): skip ANSI clear in accessible/screen-reader mode readers are not exposed to raw ANSI noise on resize. The columns state update still fires, keeping layout responsive in accessible mode. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --------- Co-authored-by: Harald Kirschner <digitarald@gmail.com> Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent 155ddde commit ce0b509

1 file changed

Lines changed: 17 additions & 3 deletions

File tree

src/ui/tui.tsx

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -65,14 +65,28 @@ const SPINNER_FRAMES = ["⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧",
6565
/** Track terminal columns reactively so resize triggers a re-render. */
6666
function useTerminalColumns(): number {
6767
const { stdout } = useStdout();
68+
const accessible = useIsScreenReaderEnabled();
6869
const [columns, setColumns] = useState(stdout.columns ?? 80);
6970
useEffect(() => {
70-
const onResize = () => setColumns(stdout.columns ?? 80);
71-
stdout.on("resize", onResize);
71+
const onResize = () => {
72+
// Terminal reflow on resize invalidates Ink's line-position tracking,
73+
// causing ghost artifacts ("screen cheese"). We use prependListener so
74+
// this fires BEFORE Ink's own resize handler, clearing the screen
75+
// before Ink re-renders — avoiding a wasted double-paint.
76+
// Skip in accessible mode to avoid screen readers announcing escape noise.
77+
if (!accessible) {
78+
stdout.write("\x1b[2J\x1b[H");
79+
}
80+
setColumns(stdout.columns ?? 80);
81+
};
82+
// prependListener ensures our clear runs before Ink's resized() handler,
83+
// which only clears on width decrease. This covers width increase and
84+
// height-only changes where Ink's log-update state goes stale.
85+
stdout.prependListener("resize", onResize);
7286
return () => {
7387
stdout.off("resize", onResize);
7488
};
75-
}, [stdout]);
89+
}, [stdout, accessible]);
7690
return columns;
7791
}
7892

0 commit comments

Comments
 (0)