aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorakbash <akbash@herdr.dev>2026-08-19 19:27:22 +0300
committerGitHub <noreply@github.com>2026-08-19 19:27:22 +0300
commit5203a5dc0f39a082938ea0f9836d6257ea7e155f (patch)
tree5c531c698cb2472bd43528b057ef958e580f2f78 /src
parenta5c69beabfc82d9c3f9563eb821139b2e0f3e14f (diff)
fix(theme): keep active terminal row visible under cursor (#2989)
refs #2987 Co-authored-by: akbash-bot <300245827+akbash-bot@users.noreply.github.com>
Diffstat (limited to 'src')
-rw-r--r--src/ui/sidebar.rs107
1 files changed, 103 insertions, 4 deletions
diff --git a/src/ui/sidebar.rs b/src/ui/sidebar.rs
index 9eede99c..a6dfbcd3 100644
--- a/src/ui/sidebar.rs
+++ b/src/ui/sidebar.rs
@@ -2,7 +2,7 @@ mod tokens;
use ratatui::{
layout::{Alignment, Rect},
- style::{Modifier, Style},
+ style::{Color, Modifier, Style},
text::{Line, Span},
widgets::Paragraph,
Frame,
@@ -748,6 +748,14 @@ pub(crate) fn collapsed_sidebar_sections(area: Rect) -> (Rect, Option<u16>, Rect
(ws_area, Some(divider_y), detail_area)
}
+fn workspace_selection_background(p: &Palette, is_active: bool) -> Color {
+ if is_active && p.selection_bg == Color::Reset {
+ p.active_row_bg
+ } else {
+ p.selection_bg
+ }
+}
+
/// Collapsed sidebar: workspace glance on top, compact agent list below.
pub(super) fn render_sidebar_collapsed(app: &AppState, frame: &mut Frame, area: Rect) {
if area.width == 0 || area.height == 0 {
@@ -787,15 +795,16 @@ pub(super) fn render_sidebar_collapsed(app: &AppState, frame: &mut Frame, area:
let (icon, icon_style) = state_icon(agg_state, agg_seen, app.status_indicators, p);
let is_selected = visible_idx == app.selected && is_navigating;
let is_active = Some(visible_idx) == app.active;
+ let selection_bg = workspace_selection_background(p, is_active);
let row_style = if is_selected {
- Style::default().bg(p.selection_bg)
+ Style::default().bg(selection_bg)
} else if is_active {
Style::default().bg(p.active_row_bg)
} else {
Style::default()
};
let num_style = if is_selected {
- Style::default().fg(p.overlay1).bg(p.selection_bg)
+ Style::default().fg(p.overlay1).bg(selection_bg)
} else if is_active {
Style::default().fg(p.text).bg(p.active_row_bg)
} else {
@@ -1248,7 +1257,7 @@ fn render_workspace_list(
if highlighted {
let bg = if selected {
- p.selection_bg
+ workspace_selection_background(p, is_active)
} else if is_dragged {
p.surface1
} else {
@@ -1785,6 +1794,96 @@ rows = [[{ token = "workspace", bold = false }, { token = "agent", dim = false }
}
#[test]
+ fn selected_active_workspace_resolves_expanded_background() {
+ let mut app = crate::app::state::AppState::test_new();
+ app.palette = crate::app::state::Palette::terminal();
+ app.workspaces = vec![Workspace::test_new("one"), Workspace::test_new("two")];
+ app.active = Some(0);
+ app.selected = 0;
+ app.mode = Mode::Navigate;
+ let area = Rect::new(0, 0, 26, 20);
+ app.view.workspace_card_areas = compute_workspace_card_areas(&app, area);
+ let active_row = app.view.workspace_card_areas[0].rect.y;
+ let inactive_row = app.view.workspace_card_areas[1].rect.y;
+ let mut terminal = Terminal::new(TestBackend::new(26, 20)).unwrap();
+ terminal
+ .draw(|frame| render_sidebar(&app, &TerminalRuntimeRegistry::new(), frame, area))
+ .unwrap();
+
+ assert_eq!(
+ terminal.backend().buffer()[(0, active_row)].bg,
+ app.palette.active_row_bg
+ );
+
+ app.selected = 1;
+ terminal
+ .draw(|frame| render_sidebar(&app, &TerminalRuntimeRegistry::new(), frame, area))
+ .unwrap();
+ assert_eq!(
+ terminal.backend().buffer()[(0, active_row)].bg,
+ app.palette.active_row_bg
+ );
+ assert_eq!(
+ terminal.backend().buffer()[(0, inactive_row)].bg,
+ app.palette.selection_bg
+ );
+
+ app.palette = crate::app::state::Palette::catppuccin();
+ app.selected = 0;
+ terminal
+ .draw(|frame| render_sidebar(&app, &TerminalRuntimeRegistry::new(), frame, area))
+ .unwrap();
+ assert_eq!(
+ terminal.backend().buffer()[(0, active_row)].bg,
+ app.palette.selection_bg
+ );
+ }
+
+ #[test]
+ fn selected_active_workspace_resolves_collapsed_background() {
+ let mut app = crate::app::state::AppState::test_new();
+ app.palette = crate::app::state::Palette::terminal();
+ app.workspaces = vec![Workspace::test_new("one"), Workspace::test_new("two")];
+ app.active = Some(0);
+ app.selected = 0;
+ app.mode = Mode::Navigate;
+ let area = Rect::new(0, 0, 5, 8);
+ let mut terminal = Terminal::new(TestBackend::new(5, 8)).unwrap();
+ terminal
+ .draw(|frame| render_sidebar_collapsed(&app, frame, area))
+ .unwrap();
+
+ let (workspace_area, _, _) = collapsed_sidebar_sections(area);
+ assert_eq!(
+ terminal.backend().buffer()[(workspace_area.x, workspace_area.y)].bg,
+ app.palette.active_row_bg
+ );
+
+ app.selected = 1;
+ terminal
+ .draw(|frame| render_sidebar_collapsed(&app, frame, area))
+ .unwrap();
+ assert_eq!(
+ terminal.backend().buffer()[(workspace_area.x, workspace_area.y)].bg,
+ app.palette.active_row_bg
+ );
+ assert_eq!(
+ terminal.backend().buffer()[(workspace_area.x, workspace_area.y + 1)].bg,
+ app.palette.selection_bg
+ );
+
+ app.palette = crate::app::state::Palette::catppuccin();
+ app.selected = 0;
+ terminal
+ .draw(|frame| render_sidebar_collapsed(&app, frame, area))
+ .unwrap();
+ assert_eq!(
+ terminal.backend().buffer()[(workspace_area.x, workspace_area.y)].bg,
+ app.palette.selection_bg
+ );
+ }
+
+ #[test]
fn space_occurrence_style_applies_without_styling_separator() {
let config: crate::config::Config = toml::from_str(
r##"