use minui::prelude::*;
fn main() -> minui::Result<()> {
let mut app = App::new(())?;
app.run(
|_state, event| !matches!(event, Event::Character('q')),
|_state, window| {
let (w, h) = window.get_size();
create_app_layout(w, h).draw(window)?;
window.flush()?;
Ok(())
},
)?;
Ok(())
}
fn create_app_layout(term_w: u16, term_h: u16) -> Container {
use minui::widgets::ContainerPadding;
let root = Container::new()
.with_position_and_size(0, 0, term_w, term_h)
.with_layout_direction(LayoutDirection::Vertical)
.with_row_gap(Gap::Pixels(1))
.with_padding(ContainerPadding::uniform(1));
let header_h: u16 = 3;
let header = Container::new()
.with_position_and_size(0, 0, term_w.saturating_sub(2), header_h)
.with_layout_direction(LayoutDirection::Vertical)
.with_border()
.with_border_chars(BorderChars::double_line())
.with_border_color(ColorPair::new(Color::LightBlue, Color::Black))
.with_title("MinUI Widget Demo")
.with_title_alignment(TitleAlignment::Center)
.with_padding(ContainerPadding::symmetric(0, 1))
.add_child(Label::new("Press 'q' to quit").with_text_color(Color::Cyan));
let footer_h: u16 = 3;
let footer = Container::new()
.with_position_and_size(0, 0, term_w.saturating_sub(2), footer_h)
.with_layout_direction(LayoutDirection::Vertical)
.with_border()
.with_border_chars(BorderChars::single_line())
.with_border_color(ColorPair::new(Color::Yellow, Color::Black))
.with_padding(ContainerPadding::symmetric(0, 1))
.add_child(Label::new("Status: Ready • Press 'q' to quit").with_text_color(Color::Yellow));
let body_h = term_h
.saturating_sub(1) .saturating_sub(1) .saturating_sub(header_h)
.saturating_sub(1) .saturating_sub(footer_h)
.saturating_sub(1);
let body = Container::new()
.with_position_and_size(0, 0, term_w.saturating_sub(2), body_h)
.with_layout_direction(LayoutDirection::Horizontal)
.with_column_gap(Gap::Pixels(2))
.with_padding(ContainerPadding::uniform(0));
let panel_w = (term_w.saturating_sub(2))
.saturating_sub(2) / 2;
let panel_h = body_h;
let text_w = panel_w.saturating_sub(4).max(1);
let text_h = panel_h.saturating_sub(4).max(1);
let left_panel = Container::new()
.with_position_and_size(0, 0, panel_w, panel_h)
.with_layout_direction(LayoutDirection::Vertical)
.with_border()
.with_border_chars(BorderChars::single_line())
.with_border_color(ColorPair::new(Color::Red, Color::Black))
.with_title("Left")
.with_padding(ContainerPadding::uniform(1))
.add_child(
TextBlock::new(
text_w,
text_h,
"This demonstrates how Containers can be arranged side-by-side. \
They support borders, titles, padding, and child layout. \
Resize the terminal to see how clipping behaves.",
)
.with_word_wrap(),
);
let right_panel = Container::new()
.with_position_and_size(0, 0, panel_w, panel_h)
.with_layout_direction(LayoutDirection::Vertical)
.with_border()
.with_border_chars(BorderChars::single_line())
.with_border_color(ColorPair::new(Color::Green, Color::Black))
.with_title("Right")
.with_padding(ContainerPadding::uniform(1))
.add_child(
TextBlock::new(
text_w,
text_h,
"Multiple widgets can coexist inside Container layouts. \
Each Container manages styling, while children provide content. \
This text is wrapped using TextBlock.",
)
.with_word_wrap(),
);
let body = body.add_child(left_panel).add_child(right_panel);
root.add_child(header).add_child(body).add_child(footer)
}