mockforge_tui/widgets/
help.rs1use ratatui::{
4 layout::{Constraint, Flex, Layout, Rect},
5 text::{Line, Span},
6 widgets::{Block, Borders, Clear, Paragraph},
7 Frame,
8};
9
10use crate::theme::Theme;
11
12const HELP_TEXT: &[(&str, &str)] = &[
13 ("Global", ""),
14 (" q / Ctrl+C", "Quit"),
15 (" Tab / Shift+Tab", "Next / Previous tab"),
16 (" 1-0", "Jump to tab 1-10"),
17 (" r", "Refresh current screen"),
18 (" /", "Open filter input"),
19 (" ?", "Toggle this help"),
20 (" :", "Command palette"),
21 ("", ""),
22 ("Navigation", ""),
23 (" j / ↓", "Scroll down"),
24 (" k / ↑", "Scroll up"),
25 (" g / G", "Jump to top / bottom"),
26 (" PgUp / PgDn", "Page up / down"),
27 (" Enter", "Select / expand"),
28 (" Esc", "Close popup / cancel"),
29 ("", ""),
30 ("Screen-specific", ""),
31 (" f", "Toggle follow mode (Logs)"),
32 (" e", "Edit selected item (Config)"),
33 (" t", "Toggle (Chaos, Time Travel)"),
34 (" s", "Sort column (Routes, Fixtures)"),
35 (" d", "Delete selected item"),
36];
37
38pub fn render(frame: &mut Frame) {
40 let area = centered_rect(60, 70, frame.area());
41
42 frame.render_widget(Clear, area);
44
45 let lines: Vec<Line> = HELP_TEXT
46 .iter()
47 .map(|(key, desc)| {
48 if desc.is_empty() {
49 Line::from(Span::styled(*key, Theme::title()))
51 } else {
52 Line::from(vec![
53 Span::styled(format!("{key:<22}"), Theme::key_hint()),
54 Span::styled(*desc, Theme::base()),
55 ])
56 }
57 })
58 .collect();
59
60 let block = Block::default()
61 .title(" Help — press ? or Esc to close ")
62 .title_style(Theme::title())
63 .borders(Borders::ALL)
64 .border_style(Theme::dim())
65 .style(Theme::surface());
66
67 let paragraph = Paragraph::new(lines).block(block);
68 frame.render_widget(paragraph, area);
69}
70
71fn centered_rect(percent_x: u16, percent_y: u16, area: Rect) -> Rect {
73 let vertical = Layout::vertical([Constraint::Percentage(percent_y)])
74 .flex(Flex::Center)
75 .split(area);
76 Layout::horizontal([Constraint::Percentage(percent_x)])
77 .flex(Flex::Center)
78 .split(vertical[0])[0]
79}