stynx_code_tui/widgets/
search_overlay.rs1use ratatui::{
2 buffer::Buffer,
3 layout::{Constraint, Layout, Rect},
4 style::{Modifier, Style},
5 text::{Line, Span},
6 widgets::{Block, Borders, Clear, List, ListItem, Paragraph, Widget},
7};
8
9use crate::theme;
10
11pub struct SearchOverlay<'a> {
12 pub query: &'a str,
13 pub results: &'a [String],
14 pub selected: usize,
15}
16
17impl<'a> SearchOverlay<'a> {
18 pub fn new(query: &'a str, results: &'a [String], selected: usize) -> Self {
19 Self { query, results, selected }
20 }
21}
22
23fn centered_rect(pct_x: u16, pct_y: u16, area: Rect) -> Rect {
24 let v = Layout::vertical([
25 Constraint::Percentage((100 - pct_y) / 2),
26 Constraint::Percentage(pct_y),
27 Constraint::Percentage((100 - pct_y) / 2),
28 ]).split(area);
29 Layout::horizontal([
30 Constraint::Percentage((100 - pct_x) / 2),
31 Constraint::Percentage(pct_x),
32 Constraint::Percentage((100 - pct_x) / 2),
33 ]).split(v[1])[1]
34}
35
36impl<'a> Widget for SearchOverlay<'a> {
37 fn render(self, area: Rect, buf: &mut Buffer) {
38 let dialog = centered_rect(60, 60, area);
39 Clear.render(dialog, buf);
40
41 let block = Block::default()
42 .title(Span::styled(" Search History ", Style::default().fg(theme::GOLD()).add_modifier(Modifier::BOLD)))
43 .borders(Borders::ALL)
44 .border_style(Style::default().fg(theme::GOLD()))
45 .style(Style::default().bg(theme::SURFACE()));
46
47 let inner = block.inner(dialog);
48 block.render(dialog, buf);
49
50 let chunks = Layout::vertical([Constraint::Length(3), Constraint::Min(1)]).split(inner);
51
52 Paragraph::new(Line::from(vec![
53 Span::styled("/ ", Style::default().fg(theme::GOLD())),
54 Span::styled(self.query, Style::default().fg(theme::TEXT())),
55 ])).block(Block::default().borders(Borders::BOTTOM).border_style(Style::default().fg(theme::HL_MED())))
56 .render(chunks[0], buf);
57
58 let items: Vec<ListItem<'_>> = self.results.iter().enumerate().map(|(i, result)| {
59 let style = if i == self.selected {
60 Style::default().fg(theme::BASE()).bg(theme::GOLD()).add_modifier(Modifier::BOLD)
61 } else {
62 Style::default().fg(theme::TEXT())
63 };
64 ListItem::new(Line::from(Span::styled(result.as_str(), style)))
65 }).collect();
66
67 List::new(items).render(chunks[1], buf);
68 }
69}