fix(tui2): render copy pill at viewport bottom (#8716)

When the selection ends on the last visible row, the copy affordance had
no space below and never rendered. Fall back to placing it above (or on
the same row for 1-row viewports) and add a regression test.
This commit is contained in:
Josh McKinney 2026-01-04 22:05:08 -08:00 committed by GitHub
parent 279283fe02
commit 5678213058
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -249,8 +249,16 @@ impl TranscriptCopyUi {
let Some((y, to_x)) = last_visible_segment else {
return;
};
// Place the pill on the row below the last visible selection segment.
let Some(y) = y.checked_add(1).filter(|y| *y < area.bottom()) else {
// Prefer placing the pill on the row below the last visible selection segment. If the
// selection ends on the last visible row, fall back to placing it above (or, if the view
// is only one row tall, on the same row).
let Some(y) = y
.checked_add(1)
.filter(|y| *y < area.bottom())
.or_else(|| y.checked_sub(1).filter(|y| *y >= area.y))
.or(Some(y))
.filter(|y| *y < area.bottom())
else {
return;
};
@ -329,4 +337,26 @@ mod tests {
assert!(!rendered.contains("ctrl + shift + c"));
assert!(ui.affordance_rect.is_some());
}
#[test]
fn pill_renders_when_selection_on_last_row() {
let area = Rect::new(0, 0, 60, 3);
let mut buf = Buffer::empty(area);
for y in 0..area.height {
for x in 2..area.width.saturating_sub(1) {
buf[(x, y)].set_symbol("X");
}
}
let mut ui = TranscriptCopyUi::new_with_shortcut(CopySelectionShortcut::CtrlShiftC);
ui.render_copy_pill(area, &mut buf, (2, 2), (2, 6), 0, 3);
let rendered = buf_to_string(&buf, area);
assert!(rendered.contains("copy"));
assert!(rendered.contains("ctrl + shift + c"));
let rect = ui.affordance_rect.expect("expected pill to render");
assert_eq!(rect.y, 1);
assert!(ui.hit_test(rect.x, rect.y));
}
}