stynx_code_tui/widgets/
thinking_panel.rs1use ratatui::{
2 buffer::Buffer,
3 layout::Rect,
4 style::{Modifier, Style},
5 text::{Line, Span},
6 widgets::{Paragraph, Widget, Wrap},
7};
8
9use crate::theme;
10use crate::widgets::spinner::FRAMES;
11
12pub struct ThinkingPanel<'a> {
13 pub text: &'a str,
14 pub spinner_frame: usize,
15}
16
17impl<'a> ThinkingPanel<'a> {
18 pub fn new(text: &'a str, spinner_frame: usize) -> Self {
19 Self { text, spinner_frame }
20 }
21}
22
23impl<'a> Widget for ThinkingPanel<'a> {
24 fn render(self, area: Rect, buf: &mut Buffer) {
25 if self.text.trim().is_empty() || area.height == 0 {
26 return;
27 }
28
29 for y in area.y..area.y + area.height {
31 for x in area.x..area.x + area.width {
32 buf[(x, y)].set_style(Style::default().bg(theme::BACKGROUND_PANEL()));
33 }
34 }
35
36 let visible_body = (area.height as usize).saturating_sub(1);
37 let mut body_lines: Vec<&str> = self
38 .text
39 .lines()
40 .filter(|l| !l.trim().is_empty())
41 .collect();
42 if body_lines.len() > visible_body {
43 body_lines = body_lines[body_lines.len() - visible_body..].to_vec();
44 }
45
46 let frame = FRAMES[self.spinner_frame % FRAMES.len()];
47
48 let mut lines: Vec<Line<'static>> = Vec::new();
49 lines.push(Line::from(vec![
50 Span::styled(
51 format!(" {frame} "),
52 Style::default()
53 .fg(theme::PRIMARY())
54 .bg(theme::BACKGROUND_PANEL())
55 .add_modifier(Modifier::BOLD),
56 ),
57 Span::styled(
58 "thinking",
59 Style::default()
60 .fg(theme::TEXT_MUTED())
61 .bg(theme::BACKGROUND_PANEL())
62 .add_modifier(Modifier::ITALIC),
63 ),
64 ]));
65 for raw in body_lines {
66 lines.push(Line::from(vec![
67 Span::styled(
68 " ",
69 Style::default().bg(theme::BACKGROUND_PANEL()),
70 ),
71 Span::styled(
72 raw.trim_end().to_string(),
73 Style::default()
74 .fg(theme::TEXT_MUTED())
75 .bg(theme::BACKGROUND_PANEL())
76 .add_modifier(Modifier::ITALIC | Modifier::DIM),
77 ),
78 ]));
79 }
80
81 Paragraph::new(lines)
82 .style(Style::default().bg(theme::BACKGROUND_PANEL()))
83 .wrap(Wrap { trim: false })
84 .render(area, buf);
85 }
86}