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