Align empty branch list message with search (#31465)

## Summary

Selection rows reserve their first two columns for the selection cursor
and render into the menu surface's left gutter. The empty-state message
reused that shifted row area even though it has no cursor prefix, so `no
matches` appeared two columns to the left of the search field.

This renders empty lists at the inset list origin while preserving the
cursor gutter for non-empty rows.
This commit is contained in:
Charlie Marsh
2026-07-08 08:57:25 -04:00
committed by GitHub
parent a52b35fcf6
commit 6849549b49
2 changed files with 39 additions and 1 deletions
@@ -1269,7 +1269,11 @@ impl Renderable for ListSelectionView {
// -- List rows --
if list_area.height > 0 {
let render_area = Rect {
x: list_area.x.saturating_sub(2),
x: if rows.is_empty() {
list_area.x
} else {
list_area.x.saturating_sub(2)
},
y: list_area.y,
width: effective_rows_width.max(1),
height: list_area.height,
@@ -1715,6 +1719,29 @@ mod tests {
);
}
#[test]
fn empty_searchable_list_aligns_message_with_search() {
let (tx_raw, _rx) = unbounded_channel::<AppEvent>();
let tx = AppEventSender::new(tx_raw);
let view = new_view(
SelectionViewParams {
title: Some("Select a base branch".to_string()),
footer_hint: Some(standard_popup_hint_line()),
is_searchable: true,
search_placeholder: Some("Type to search branches".to_string()),
..Default::default()
},
tx,
);
let rendered = render_lines_with_width(&view, /*width*/ 48)
.lines()
.map(str::trim_end)
.collect::<Vec<_>>()
.join("\n");
assert_snapshot!("list_selection_empty_searchable", rendered);
}
#[test]
fn paste_appends_to_search_query_and_filters_items() {
let (tx_raw, _rx) = unbounded_channel::<AppEvent>();
@@ -0,0 +1,11 @@
---
source: tui/src/bottom_pane/list_selection_view.rs
expression: rendered
---
Select a base branch
Type to search branches
no matches
Press enter to confirm or esc to go back