#11584

tui: overlay does not cover terminal images (compositeTuiLine passes image rows through)

OpenEvilIrvingopened 10d ago

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 dropped

In 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

0

No activity yet.