cli_tutor/ui/
help_overlay.rs1use crate::app::App;
2use ratatui::{
3 layout::{Constraint, Direction, Layout, Rect},
4 style::{Color, Modifier, Style},
5 text::{Line, Span},
6 widgets::{Block, Borders, Clear, Paragraph},
7 Frame,
8};
9
10pub fn render(_app: &App, frame: &mut Frame, area: Rect) {
11 let overlay = centered_rect(60, 70, area);
12 frame.render_widget(Clear, overlay);
13
14 let lines = vec![
15 Line::from(Span::styled(
16 "Keyboard Reference",
17 Style::default()
18 .add_modifier(Modifier::BOLD)
19 .fg(Color::Cyan),
20 )),
21 Line::from(""),
22 key_line("↑ / ↓", "Navigate module list"),
23 key_line("Tab", "Cycle view: Intro → Examples → Exercise"),
24 key_line("→ / n", "Next exercise"),
25 key_line("← / p", "Previous exercise"),
26 key_line("Enter", "Submit command"),
27 key_line("h", "Reveal next hint"),
28 key_line("s", "Show/hide solution"),
29 key_line("f", "Toggle file viewer"),
30 key_line("r", "Reset exercise"),
31 key_line("Ctrl+L", "Clear output panel"),
32 key_line("?", "Toggle this help overlay"),
33 key_line("q / Ctrl+C", "Quit"),
34 Line::from(""),
35 Line::from(Span::styled(
36 "Press ? or Esc to close",
37 Style::default().fg(Color::DarkGray),
38 )),
39 ];
40
41 let para = Paragraph::new(lines).block(
42 Block::default()
43 .borders(Borders::ALL)
44 .title(" Help ")
45 .style(Style::default().bg(Color::Black)),
46 );
47
48 frame.render_widget(para, overlay);
49}
50
51fn key_line(key: &str, desc: &str) -> Line<'static> {
52 Line::from(vec![
53 Span::styled(
54 format!(" {:<15}", key),
55 Style::default()
56 .fg(Color::Yellow)
57 .add_modifier(Modifier::BOLD),
58 ),
59 Span::raw(desc.to_string()),
60 ])
61}
62
63fn centered_rect(percent_x: u16, percent_y: u16, r: Rect) -> Rect {
64 let vert = Layout::default()
65 .direction(Direction::Vertical)
66 .constraints([
67 Constraint::Percentage((100 - percent_y) / 2),
68 Constraint::Percentage(percent_y),
69 Constraint::Percentage((100 - percent_y) / 2),
70 ])
71 .split(r);
72 Layout::default()
73 .direction(Direction::Horizontal)
74 .constraints([
75 Constraint::Percentage((100 - percent_x) / 2),
76 Constraint::Percentage(percent_x),
77 Constraint::Percentage((100 - percent_x) / 2),
78 ])
79 .split(vert[1])[1]
80}