What happened?
An overlay does not cover a terminal image. If a transcript row holds a Kitty or iTerm2 image and an overlay sits on top of it, the image stays visible and the overlay simply has no rows there: no panel background, no text, a hole exactly the size of the image.
It is deliberate-looking code in packages/tui/src/tui.ts:
export function compositeTuiLine(baseLine, overlayLine, startCol, overlayWidth, totalWidth) {
if (isImageLine(baseLine))
return baseLine;so any image row inside the overlay rectangle is passed through untouched.
Steps to reproduce
No terminal needed:
import { compositeTuiLine, encodeKitty, allocateImageId } from "@earendil-works/pi-tui";
const png = "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mP8z8BQDwAEhQGAhKmMIQAAAABJRU5ErkJggg==";
const row = encodeKitty(png, { columns: 20, rows: 5, imageId: allocateImageId() }) + " ".repeat(20);
const panel = "OVERLAY PANEL ROW".padEnd(40, " ");
compositeTuiLine(row, panel, 30, 40, 100) === row; // true, overlay droppedIn pi: open a session where an image was rendered (read a PNG), then open any overlay that covers it (ui.custom(..., { overlay: true })). The image is drawn over the panel.
Expected behavior
The overlay wins inside its own rectangle. Either delete the Kitty placements that intersect the overlay bounds and re-emit the image when the overlay closes, or at minimum let the panel's lines replace the covered rows.
Why it matters
A bordered panel with an opaque background is the normal way to show a picker or dialog. With an image above it, the panel gets a translucent-looking hole and the user reads the image through the UI. Sizing or background changes in the extension cannot fix it, since the row never reaches compositing.
Version
@earendil-works/pi-tui 1.4.0 (kitty and iTerm2 protocols; compositeTuiLine behaves the same for both).
I can implement this if it is wanted: track image placements per row, and on overlay render/close delete and re-emit the intersecting ones.
Activity
0No activity yet.