From a87d3dcd7fb98be017eaaeca6161b454bcff678c Mon Sep 17 00:00:00 2001 From: David Hagerty Date: Sat, 24 Jan 2026 07:48:53 -0800 Subject: [PATCH] feat(tui): add basic UI layout with tab bar and status bar --- src/tui/mod.rs | 2 ++ src/tui/ui.rs | 52 ++++++++++++++++++++++++++++++++++++++++++++++---- 2 files changed, 50 insertions(+), 4 deletions(-) diff --git a/src/tui/mod.rs b/src/tui/mod.rs index f9c829a..13a8cc7 100644 --- a/src/tui/mod.rs +++ b/src/tui/mod.rs @@ -1,7 +1,9 @@ mod app; mod ui; +pub mod widgets; pub use app::{App, ActiveTab}; +pub use ui::draw; use std::io; use std::panic; diff --git a/src/tui/ui.rs b/src/tui/ui.rs index 45ee10c..4937bd4 100644 --- a/src/tui/ui.rs +++ b/src/tui/ui.rs @@ -1,6 +1,50 @@ -use ratatui::Frame; -use crate::tui::App; +use ratatui::{ + layout::{Constraint, Direction, Layout}, + style::{Color, Style}, + text::{Line, Span}, + widgets::{Block, Borders, Paragraph}, + Frame, +}; -pub fn draw(_frame: &mut Frame, _app: &App) { - // Placeholder - will be implemented in Task 4 +use crate::tui::{App, ActiveTab}; +use crate::tui::widgets::TabBar; + +pub fn draw(frame: &mut Frame, app: &App) { + let chunks = Layout::default() + .direction(Direction::Vertical) + .constraints([ + Constraint::Length(1), // Tab bar + Constraint::Min(0), // Main content + Constraint::Length(1), // Status bar + ]) + .split(frame.area()); + + // Tab bar + frame.render_widget(TabBar::new(app.active_tab), chunks[0]); + + // Main content area + let content_block = Block::default() + .borders(Borders::ALL) + .title(match app.active_tab { + ActiveTab::Dashboard => " Dashboard ", + ActiveTab::Planning => " Planning ", + ActiveTab::Execution => " Execution ", + }); + + let placeholder = Paragraph::new(match app.active_tab { + ActiveTab::Dashboard => "Dashboard view - coming soon", + ActiveTab::Planning => "Planning view - coming soon", + ActiveTab::Execution => "Execution view - coming soon", + }) + .block(content_block); + + frame.render_widget(placeholder, chunks[1]); + + // Status bar + let status = Line::from(vec![ + Span::raw(" q quit │ 1/2/3 switch tabs │ Tab cycle │ ? help "), + ]); + let status_bar = Paragraph::new(status) + .style(Style::default().bg(Color::DarkGray)); + frame.render_widget(status_bar, chunks[2]); } -- 2.51.2