chore(deps/ui): upgrade ratatui 0.29 and refresh gradients
Acceptance Criteria: - Workspace builds against ratatui 0.29, crossterm 0.28.1, and tui-textarea 0.7 with palette support enabled - Chat header context and usage gauges render with refreshed tailwind gradients - Header layout uses the Flex API to balance top-row metadata across window widths Test Notes: - cargo test -p owlen-tui
This commit is contained in:
@@ -34,9 +34,9 @@ futures = "0.3"
|
||||
futures-util = "0.3"
|
||||
|
||||
# TUI framework
|
||||
ratatui = "0.28"
|
||||
crossterm = "0.28"
|
||||
tui-textarea = "0.6"
|
||||
ratatui = { version = "0.29", features = ["palette"] }
|
||||
crossterm = "0.28.1"
|
||||
tui-textarea = "0.7"
|
||||
|
||||
# HTTP client and JSON handling
|
||||
reqwest = { version = "0.12", default-features = false, features = ["json", "stream", "rustls-tls"] }
|
||||
|
||||
@@ -17,7 +17,7 @@ serde_json = { workspace = true }
|
||||
thiserror = { workspace = true }
|
||||
tokio = { workspace = true }
|
||||
unicode-segmentation = "1.11"
|
||||
unicode-width = "0.1"
|
||||
unicode-width = "0.2"
|
||||
uuid = { workspace = true }
|
||||
textwrap = { workspace = true }
|
||||
futures = { workspace = true }
|
||||
|
||||
@@ -7,4 +7,4 @@ description = "Lightweight markdown to ratatui::Text renderer for OWLEN"
|
||||
|
||||
[dependencies]
|
||||
ratatui = { workspace = true }
|
||||
unicode-width = "0.1"
|
||||
unicode-width = "0.2"
|
||||
|
||||
@@ -17,7 +17,7 @@ ratatui = { workspace = true }
|
||||
crossterm = { workspace = true }
|
||||
tui-textarea = { workspace = true }
|
||||
textwrap = { workspace = true }
|
||||
unicode-width = "0.1"
|
||||
unicode-width = "0.2"
|
||||
unicode-segmentation = "1.11"
|
||||
async-trait = "0.1"
|
||||
globset = "0.4"
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
use owlen_core::theme::Theme;
|
||||
use ratatui::style::Color;
|
||||
use ratatui::style::{Color, palette::tailwind};
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
pub struct GlassPalette {
|
||||
@@ -18,40 +18,40 @@ impl GlassPalette {
|
||||
let luminance = color_luminance(theme.background);
|
||||
if luminance < 0.5 {
|
||||
Self {
|
||||
active: Color::Rgb(26, 28, 40),
|
||||
inactive: Color::Rgb(18, 20, 30),
|
||||
highlight: Color::Rgb(32, 35, 48),
|
||||
track: Color::Rgb(35, 38, 50),
|
||||
label: Color::Rgb(241, 245, 249),
|
||||
shadow: Color::Rgb(8, 9, 16),
|
||||
active: tailwind::SLATE.c900,
|
||||
inactive: tailwind::SLATE.c800,
|
||||
highlight: tailwind::SLATE.c800,
|
||||
track: tailwind::SLATE.c700,
|
||||
label: tailwind::SLATE.c100,
|
||||
shadow: tailwind::SLATE.c950,
|
||||
context_stops: [
|
||||
Color::Rgb(56, 189, 248),
|
||||
Color::Rgb(250, 204, 21),
|
||||
Color::Rgb(248, 113, 113),
|
||||
tailwind::SKY.c400,
|
||||
tailwind::AMBER.c300,
|
||||
tailwind::ROSE.c400,
|
||||
],
|
||||
usage_stops: [
|
||||
Color::Rgb(34, 211, 238),
|
||||
Color::Rgb(250, 204, 21),
|
||||
Color::Rgb(248, 113, 113),
|
||||
tailwind::CYAN.c400,
|
||||
tailwind::AMBER.c300,
|
||||
tailwind::ROSE.c400,
|
||||
],
|
||||
}
|
||||
} else {
|
||||
Self {
|
||||
active: Color::Rgb(242, 247, 255),
|
||||
inactive: Color::Rgb(229, 235, 250),
|
||||
highlight: Color::Rgb(224, 230, 248),
|
||||
track: Color::Rgb(203, 210, 230),
|
||||
label: Color::Rgb(31, 41, 55),
|
||||
shadow: Color::Rgb(200, 205, 220),
|
||||
active: tailwind::ZINC.c100,
|
||||
inactive: tailwind::ZINC.c200,
|
||||
highlight: tailwind::ZINC.c200,
|
||||
track: tailwind::ZINC.c300,
|
||||
label: tailwind::SLATE.c700,
|
||||
shadow: tailwind::ZINC.c300,
|
||||
context_stops: [
|
||||
Color::Rgb(59, 130, 246),
|
||||
Color::Rgb(234, 179, 8),
|
||||
Color::Rgb(239, 68, 68),
|
||||
tailwind::BLUE.c500,
|
||||
tailwind::AMBER.c400,
|
||||
tailwind::ROSE.c500,
|
||||
],
|
||||
usage_stops: [
|
||||
Color::Rgb(20, 184, 166),
|
||||
Color::Rgb(245, 158, 11),
|
||||
Color::Rgb(239, 68, 68),
|
||||
tailwind::TEAL.c400,
|
||||
tailwind::AMBER.c400,
|
||||
tailwind::ROSE.c500,
|
||||
],
|
||||
}
|
||||
}
|
||||
@@ -60,7 +60,7 @@ impl GlassPalette {
|
||||
|
||||
pub fn gradient_color(stops: &[Color; 3], t: f64) -> Color {
|
||||
let clamped = t.clamp(0.0, 1.0);
|
||||
let segments = stops.len() - 1;
|
||||
let segments = stops.len().saturating_sub(1).max(1);
|
||||
let scaled = clamped * segments as f64;
|
||||
let index = scaled.floor() as usize;
|
||||
let frac = scaled - index as f64;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
use log::Level;
|
||||
use pathdiff::diff_paths;
|
||||
use ratatui::Frame;
|
||||
use ratatui::layout::{Alignment, Constraint, Direction, Layout, Rect};
|
||||
use ratatui::layout::{Alignment, Constraint, Direction, Flex, Layout, Rect};
|
||||
use ratatui::style::{Color, Modifier, Style};
|
||||
use ratatui::text::{Line, Span};
|
||||
use ratatui::widgets::block::Padding;
|
||||
@@ -421,9 +421,8 @@ fn render_chat_header(
|
||||
constraints.push(Constraint::Min(2));
|
||||
}
|
||||
|
||||
let rows = Layout::default()
|
||||
.direction(Direction::Vertical)
|
||||
.constraints(constraints)
|
||||
let rows = Layout::vertical(constraints)
|
||||
.flex(Flex::Start)
|
||||
.split(highlight_area);
|
||||
|
||||
render_header_top(frame, rows[0], app, palette, theme);
|
||||
@@ -444,9 +443,8 @@ fn render_header_top(
|
||||
return;
|
||||
}
|
||||
|
||||
let columns = Layout::default()
|
||||
.direction(Direction::Horizontal)
|
||||
.constraints([Constraint::Percentage(60), Constraint::Percentage(40)])
|
||||
let columns = Layout::horizontal([Constraint::Percentage(60), Constraint::Percentage(40)])
|
||||
.flex(Flex::SpaceBetween)
|
||||
.split(area);
|
||||
|
||||
let mut left_spans = Vec::new();
|
||||
@@ -558,9 +556,8 @@ fn render_header_bars(
|
||||
return;
|
||||
}
|
||||
|
||||
let columns = Layout::default()
|
||||
.direction(Direction::Horizontal)
|
||||
.constraints([Constraint::Percentage(45), Constraint::Percentage(55)])
|
||||
let columns = Layout::horizontal([Constraint::Percentage(45), Constraint::Percentage(55)])
|
||||
.flex(Flex::SpaceBetween)
|
||||
.split(area);
|
||||
|
||||
render_context_column(frame, columns[0], app, palette, theme);
|
||||
@@ -823,14 +820,12 @@ pub fn render_chat(frame: &mut Frame<'_>, app: &mut ChatApp) {
|
||||
let header_height = header_height.max(3).min(frame_area.height);
|
||||
|
||||
let segments = if frame_area.height <= header_height {
|
||||
Layout::default()
|
||||
.direction(Direction::Vertical)
|
||||
.constraints([Constraint::Length(frame_area.height)])
|
||||
Layout::vertical([Constraint::Length(frame_area.height)])
|
||||
.flex(Flex::Start)
|
||||
.split(frame_area)
|
||||
} else {
|
||||
Layout::default()
|
||||
.direction(Direction::Vertical)
|
||||
.constraints([Constraint::Length(header_height), Constraint::Min(1)])
|
||||
Layout::vertical([Constraint::Length(header_height), Constraint::Min(1)])
|
||||
.flex(Flex::Start)
|
||||
.split(frame_area)
|
||||
};
|
||||
|
||||
@@ -874,17 +869,15 @@ pub fn render_chat(frame: &mut Frame<'_>, app: &mut ChatApp) {
|
||||
} else {
|
||||
let max_sidebar = content_area.width.saturating_sub(30).max(10);
|
||||
let sidebar_width = app.file_panel_width().min(max_sidebar).max(10);
|
||||
let segments = Layout::default()
|
||||
.direction(Direction::Horizontal)
|
||||
.constraints([Constraint::Length(sidebar_width), Constraint::Min(30)])
|
||||
let segments = Layout::horizontal([Constraint::Length(sidebar_width), Constraint::Min(30)])
|
||||
.flex(Flex::Start)
|
||||
.split(content_area);
|
||||
(Some(segments[0]), segments[1])
|
||||
};
|
||||
|
||||
let (chat_area, code_area) = if app.should_show_code_view() {
|
||||
let segments = Layout::default()
|
||||
.direction(Direction::Horizontal)
|
||||
.constraints([Constraint::Percentage(65), Constraint::Percentage(35)])
|
||||
let segments = Layout::horizontal([Constraint::Percentage(65), Constraint::Percentage(35)])
|
||||
.flex(Flex::Start)
|
||||
.split(main_area);
|
||||
(segments[0], Some(segments[1]))
|
||||
} else {
|
||||
@@ -5653,29 +5646,21 @@ fn render_symbol_search(frame: &mut Frame<'_>, app: &mut ChatApp) {
|
||||
}
|
||||
|
||||
fn centered_rect(percent_x: u16, percent_y: u16, area: Rect) -> Rect {
|
||||
let vertical = Layout::default()
|
||||
.direction(Direction::Vertical)
|
||||
.constraints(
|
||||
[
|
||||
Constraint::Percentage((100 - percent_y) / 2),
|
||||
Constraint::Percentage(percent_y),
|
||||
Constraint::Percentage((100 - percent_y) / 2),
|
||||
]
|
||||
.as_ref(),
|
||||
)
|
||||
.split(area);
|
||||
let vertical = Layout::vertical([
|
||||
Constraint::Percentage((100 - percent_y) / 2),
|
||||
Constraint::Percentage(percent_y),
|
||||
Constraint::Percentage((100 - percent_y) / 2),
|
||||
])
|
||||
.flex(Flex::Center)
|
||||
.split(area);
|
||||
|
||||
Layout::default()
|
||||
.direction(Direction::Horizontal)
|
||||
.constraints(
|
||||
[
|
||||
Constraint::Percentage((100 - percent_x) / 2),
|
||||
Constraint::Percentage(percent_x),
|
||||
Constraint::Percentage((100 - percent_x) / 2),
|
||||
]
|
||||
.as_ref(),
|
||||
)
|
||||
.split(vertical[1])[1]
|
||||
Layout::horizontal([
|
||||
Constraint::Percentage((100 - percent_x) / 2),
|
||||
Constraint::Percentage(percent_x),
|
||||
Constraint::Percentage((100 - percent_x) / 2),
|
||||
])
|
||||
.flex(Flex::Center)
|
||||
.split(vertical[1])[1]
|
||||
}
|
||||
|
||||
/// Format tool output JSON into a nice human-readable format
|
||||
|
||||
Reference in New Issue
Block a user