diff --git a/src/app/input.rs b/src/app/input.rs index 17f283c8..e483029b 100644 --- a/src/app/input.rs +++ b/src/app/input.rs @@ -1971,6 +1971,11 @@ impl AppState { if in_sidebar { if self.sidebar_collapsed { + if self.on_collapsed_sidebar_toggle(mouse.column, mouse.row) { + self.sidebar_collapsed = false; + return None; + } + if let Some(idx) = self.collapsed_workspace_at_row(mouse.row) { self.switch_workspace(idx); self.mode = Mode::Terminal; @@ -2316,6 +2321,18 @@ impl AppState { && row < sidebar.y + sidebar.height } + fn on_collapsed_sidebar_toggle(&self, col: u16, row: u16) -> bool { + if !self.sidebar_collapsed { + return false; + } + let rect = crate::ui::collapsed_sidebar_toggle_rect(self.view.sidebar_rect); + rect.width > 0 + && col >= rect.x + && col < rect.x + rect.width + && row >= rect.y + && row < rect.y + rect.height + } + fn set_manual_sidebar_width(&mut self, divider_col: u16) { let sidebar = self.view.sidebar_rect; let width = divider_col.saturating_sub(sidebar.x).saturating_add(1); @@ -3620,6 +3637,23 @@ mod tests { assert_eq!(app.state.mode, Mode::Terminal); } + #[test] + fn clicking_collapsed_sidebar_toggle_expands_sidebar() { + let mut app = app_for_mouse_test(); + app.state.sidebar_collapsed = true; + app.state.view.sidebar_rect = Rect::new(0, 0, 4, 20); + app.state.view.terminal_area = Rect::new(4, 0, 80, 20); + + let toggle = crate::ui::collapsed_sidebar_toggle_rect(app.state.view.sidebar_rect); + app.handle_mouse(mouse( + MouseEventKind::Down(MouseButton::Left), + toggle.x, + toggle.y, + )); + + assert!(!app.state.sidebar_collapsed); + } + #[test] fn clicking_workspace_switches_on_mouse_up() { let mut app = app_for_mouse_test(); diff --git a/src/ui.rs b/src/ui.rs index 3783dd5c..4a734d0d 100644 --- a/src/ui.rs +++ b/src/ui.rs @@ -1054,6 +1054,16 @@ fn render_agent_detail(app: &AppState, frame: &mut Frame, area: Rect) { } } +pub(crate) fn collapsed_sidebar_toggle_rect(area: Rect) -> Rect { + let bottom_y = area.y + area.height.saturating_sub(1); + let content_w = area.width.saturating_sub(1); + if content_w == 0 || area.height == 0 { + return Rect::default(); + } + let x = area.x + content_w / 2; + Rect::new(x, bottom_y, 1, 1) +} + fn render_sidebar_toggle( app: &AppState, frame: &mut Frame, @@ -1066,9 +1076,8 @@ fn render_sidebar_toggle( if !collapsed { return; } - let bottom_y = area.y + area.height.saturating_sub(1); - let content_w = area.width.saturating_sub(1); - if content_w == 0 || area.height == 0 { + let toggle_area = collapsed_sidebar_toggle_rect(area); + if toggle_area == Rect::default() { return; } let icon_style = if app.update_available.is_some() { @@ -1076,8 +1085,6 @@ fn render_sidebar_toggle( } else { Style::default().fg(p.overlay0) }; - let x = area.x + content_w / 2; - let toggle_area = Rect::new(x, bottom_y, 1, 1); frame.render_widget(Paragraph::new(Span::styled("ยป", icon_style)), toggle_area); }