1use color_eyre::Result;
20use ratatui::{
21 crossterm::event::{self, Event, KeyCode, KeyEventKind},
22 layout::{Constraint, Flex, Layout, Rect},
23 style::Stylize,
24 widgets::{Block, Clear, Paragraph, Wrap},
25 DefaultTerminal, Frame,
26};
27
28fn main() -> Result<()> {
29 color_eyre::install()?;
30 let terminal = ratatui::init();
31 let app_result = App::default().run(terminal);
32 ratatui::restore();
33 app_result
34}
35
36#[derive(Default)]
37struct App {
38 show_popup: bool,
39}
40
41impl App {
42 fn run(mut self, mut terminal: DefaultTerminal) -> Result<()> {
43 loop {
44 terminal.draw(|frame| self.draw(frame))?;
45
46 if let Event::Key(key) = event::read()? {
47 if key.kind == KeyEventKind::Press {
48 match key.code {
49 KeyCode::Char('q') => return Ok(()),
50 KeyCode::Char('p') => self.show_popup = !self.show_popup,
51 _ => {}
52 }
53 }
54 }
55 }
56 }
57
58 fn draw(&self, frame: &mut Frame) {
59 let area = frame.area();
60
61 let vertical = Layout::vertical([Constraint::Percentage(20), Constraint::Percentage(80)]);
62 let [instructions, content] = vertical.areas(area);
63
64 let text = if self.show_popup {
65 "Press p to close the popup"
66 } else {
67 "Press p to show the popup"
68 };
69 let paragraph = Paragraph::new(text.slow_blink())
70 .centered()
71 .wrap(Wrap { trim: true });
72 frame.render_widget(paragraph, instructions);
73
74 let block = Block::bordered().title("Content").on_blue();
75 frame.render_widget(block, content);
76
77 if self.show_popup {
78 let block = Block::bordered().title("Popup");
79 let area = popup_area(area, 60, 20);
80 frame.render_widget(Clear, area); frame.render_widget(block, area);
82 }
83 }
84}
85
86fn popup_area(area: Rect, percent_x: u16, percent_y: u16) -> Rect {
88 let vertical = Layout::vertical([Constraint::Percentage(percent_y)]).flex(Flex::Center);
89 let horizontal = Layout::horizontal([Constraint::Percentage(percent_x)]).flex(Flex::Center);
90 let [area] = vertical.areas(area);
91 let [area] = horizontal.areas(area);
92 area
93}