From e46387acc8bddbb66efbc062a64acf69eccd09db Mon Sep 17 00:00:00 2001 From: Lstarsky0 <59827030+Lstarsky0@users.noreply.github.com> Date: Mon, 19 Oct 2026 01:28:54 +0800 Subject: [PATCH] fix(tui): show a scroll rail on a settings choice list that doesn't fit Opening a setting's choices in /settings shows as many options as fit and scrolls to keep the selected one in view, but nothing on screen says the list goes on. Language has 17 options; at 80x24 the list ends at "11. de", at 60x16 at "5. zh-Hant", and there is no hint the other languages exist until you arrow past the last row. Theme is the same. The settings list behind it already paints render_panel_scroll_rail for this, so use it here too, on the rows the options occupy. It is painted after the paragraph, because the paragraph restyles its whole area, and the labels give up one column only when the rail is drawn, so a long label can't run under it. A list that fits draws no rail and renders as before. The 80x24 edit-theme golden gains the rail on its option rows; the 120x32 one fits all 17 themes and does not change. Signed-off-by: Lstarsky0 <59827030+Lstarsky0@users.noreply.github.com> --- .../tui/src/tui/goldens/edit_theme_80x24.txt | 22 +++++++++---------- crates/tui/src/tui/views/mod.rs | 21 +++++++++++++++++- 2 files changed, 31 insertions(+), 12 deletions(-) diff --git a/crates/tui/src/tui/goldens/edit_theme_80x24.txt b/crates/tui/src/tui/goldens/edit_theme_80x24.txt index 3c4f03e6ae..01c3782f4b 100644 --- a/crates/tui/src/tui/goldens/edit_theme_80x24.txt +++ b/crates/tui/src/tui/goldens/edit_theme_80x24.txt @@ -7,17 +7,17 @@ Current: underwater Choose: - 1. system - 2. terminal - 3. shoreline - 4. shoreline-light - ▸ 5. underwater - 6. underwater-retro - 7. dark - 8. light - 9. grayscale - 10. catppuccin-mocha - 11. tokyo-night + 1. system █ + 2. terminal █ + 3. shoreline █ + 4. shoreline-light █ + ▸ 5. underwater █ + 6. underwater-retro █ + 7. dark █ + 8. light █ + 9. grayscale │ + 10. catppuccin-mocha │ + 11. tokyo-night │ [ Apply ] [ Cancel ] ↑/↓ or click choose · Enter/Apply · Esc/Cancel · 1-9 jump ────────────────────────────────────────────────────────────────────────────── diff --git a/crates/tui/src/tui/views/mod.rs b/crates/tui/src/tui/views/mod.rs index 51571847a3..94c2f8c0cd 100644 --- a/crates/tui/src/tui/views/mod.rs +++ b/crates/tui/src/tui/views/mod.rs @@ -4367,6 +4367,7 @@ impl ModalView for ConfigView { let inner = render_underwater_surface(area, buf, self.tr(MessageId::ConfigModalTitle).to_string()); + let mut choice_rail = None; let (lines, footer) = if let Some(edit) = self.editing.as_ref() { *self.last_choice_hitboxes.borrow_mut() = Vec::new(); *self.last_editor_controls.borrow_mut() = Vec::new(); @@ -4463,6 +4464,21 @@ impl ModalView for ConfigView { .min(max_start); let end = (start + visible_options).min(choices.len()); let mut hitboxes = Vec::new(); + let scrolls = visible_options < choices.len(); + if scrolls { + choice_rail = Some(( + Rect { + x: inner.x, + y: inner.y.saturating_add(lines.len() as u16), + width: inner.width, + height: u16::try_from(visible_options).unwrap_or(u16::MAX), + }, + choices.len(), + start, + visible_options, + )); + } + let label_width = usize::from(inner.width).saturating_sub(8 + usize::from(scrolls)); for (choice_idx, choice) in choices.iter().enumerate().take(end).skip(start) { let selected = choice_idx == edit.selected_choice; @@ -4481,7 +4497,7 @@ impl ModalView for ConfigView { let mut line = Line::from(format!( " {marker} {:>2}. {}", choice_idx + 1, - truncate_view_text(&label, usize::from(inner.width).saturating_sub(8)) + truncate_view_text(&label, label_width) )); line.style = if selected { menu_style::selected_row_style() @@ -4547,6 +4563,9 @@ impl ModalView for ConfigView { .style(Style::default().fg(palette::TEXT_PRIMARY)) .scroll((0, 0)) .render(body, buf); + if let Some((rail, total, offset, visible)) = choice_rail { + render_panel_scroll_rail(rail, buf, total, offset, visible, true); + } if content.height > 0 { self.render_editor_controls( Rect {