Skip to main content

hello_layout/
hello_layout.rs

1//! Minimal example showing how to use `BobaStyle` + `Surface` layout.
2//!
3//! Run with: `cargo run --example hello_layout`
4
5use {
6    bobatea::{
7        App, AppEvent, View,
8        components::{
9            border::Border,
10            style::{BobaStyle, hex_color},
11        },
12        events::{EventTarget, SubscriptionPriority},
13        surface::{Cell, Position, join_horizontal, join_vertical, place},
14        theme::Theme,
15    },
16    crossterm::event::KeyCode,
17    ratatui::{
18        Frame,
19        style::{Color, Style},
20    },
21};
22
23struct HelloView;
24
25impl View for HelloView {
26    fn mount(&self, app: &EventTarget<AppEvent>) {
27        let app_for_quit = app.clone();
28        app.on_key(SubscriptionPriority::High, move |ev, key| {
29            if key.code == KeyCode::Char('q') {
30                ev.cancel();
31                app_for_quit.emit(AppEvent::Quit);
32            }
33        })
34        .forget();
35    }
36
37    fn render(&self, ctx: &mut Frame<'_>, _theme: &Theme) {
38        let area = ctx.area();
39        let buf = ctx.buffer_mut();
40
41        // Clear background
42        for y in area.top()..area.bottom() {
43            for x in area.left()..area.right() {
44                buf[(x, y)].reset();
45                buf[(x, y)].set_bg(Color::Black);
46            }
47        }
48
49        // Build some styled text surfaces
50        let hello = BobaStyle::new().fg(hex_color("#FF5F87")).bg(Color::Black).bold().render("Hello");
51
52        let world = BobaStyle::new().fg(hex_color("#A550DF")).bg(Color::Black).italic().render("World");
53
54        // Join them horizontally with a divider
55        let divider = BobaStyle::new().fg(Color::DarkGray).render("│");
56        let joined = join_horizontal(Position::Center, &[hello, divider, world]);
57
58        // Put a rounded border around it
59        let boxed = BobaStyle::new()
60            .border(Border::rounded())
61            .border_fg(hex_color("#874BFD"))
62            .padding(1, 2, 1, 2)
63            .render_surface(&joined);
64
65        // Add a small label below
66        let label = BobaStyle::new().fg(Color::DarkGray).margin_top(1).render("press 'q' to quit");
67
68        let doc = join_vertical(Position::Center, &[boxed, label]);
69
70        // Center the whole thing on screen
71        let centered = place(
72            area.width as usize,
73            area.height as usize,
74            Position::Center,
75            Position::Center,
76            &doc,
77            &Cell::blank(Style::default().bg(Color::Black)),
78        );
79
80        // Render into the frame buffer
81        centered.render_to_area(area, buf);
82    }
83}
84
85fn main() {
86    let rt = tokio::runtime::Builder::new_multi_thread().enable_all().build().unwrap();
87    rt.block_on(async {
88        App::new(HelloView).run().await.unwrap();
89    });
90}