An AI agent built to do Ralph loops - plan mode for planning and ralph mode for implementing.

feat(tui): add basic UI layout with tab bar and status bar

+50 -4
+2
src/tui/mod.rs
··· 1 1 mod app; 2 2 mod ui; 3 + pub mod widgets; 3 4 4 5 pub use app::{App, ActiveTab}; 6 + pub use ui::draw; 5 7 6 8 use std::io; 7 9 use std::panic;
+48 -4
src/tui/ui.rs
··· 1 - use ratatui::Frame; 2 - use crate::tui::App; 1 + use ratatui::{ 2 + layout::{Constraint, Direction, Layout}, 3 + style::{Color, Style}, 4 + text::{Line, Span}, 5 + widgets::{Block, Borders, Paragraph}, 6 + Frame, 7 + }; 3 8 4 - pub fn draw(_frame: &mut Frame, _app: &App) { 5 - // Placeholder - will be implemented in Task 4 9 + use crate::tui::{App, ActiveTab}; 10 + use crate::tui::widgets::TabBar; 11 + 12 + pub fn draw(frame: &mut Frame, app: &App) { 13 + let chunks = Layout::default() 14 + .direction(Direction::Vertical) 15 + .constraints([ 16 + Constraint::Length(1), // Tab bar 17 + Constraint::Min(0), // Main content 18 + Constraint::Length(1), // Status bar 19 + ]) 20 + .split(frame.area()); 21 + 22 + // Tab bar 23 + frame.render_widget(TabBar::new(app.active_tab), chunks[0]); 24 + 25 + // Main content area 26 + let content_block = Block::default() 27 + .borders(Borders::ALL) 28 + .title(match app.active_tab { 29 + ActiveTab::Dashboard => " Dashboard ", 30 + ActiveTab::Planning => " Planning ", 31 + ActiveTab::Execution => " Execution ", 32 + }); 33 + 34 + let placeholder = Paragraph::new(match app.active_tab { 35 + ActiveTab::Dashboard => "Dashboard view - coming soon", 36 + ActiveTab::Planning => "Planning view - coming soon", 37 + ActiveTab::Execution => "Execution view - coming soon", 38 + }) 39 + .block(content_block); 40 + 41 + frame.render_widget(placeholder, chunks[1]); 42 + 43 + // Status bar 44 + let status = Line::from(vec![ 45 + Span::raw(" q quit │ 1/2/3 switch tabs │ Tab cycle │ ? help "), 46 + ]); 47 + let status_bar = Paragraph::new(status) 48 + .style(Style::default().bg(Color::DarkGray)); 49 + frame.render_widget(status_bar, chunks[2]); 6 50 }