Watch
1
0
Fork
You've already forked souveraine
0
souveraine/src/ui/theme.rs
Fimeg 61bf34177e feat(tui): tuie widget-toolkit engine behind --engine tuie
Introduce a parallel TUI built on the tuie widget toolkit, selectable at
runtime with `--engine tuie`. ratatui remains the default and its
crossterm/ratatui deps are retained, so default users see no behavior
change; this lands the full screen/widget tree for the new engine
side-by-side with the existing one.

Engine wiring:
- Cargo: add `tuie` (harmonious, images features)
- main.rs: `--engine` flag + run_tuie_tui() entry path
- src/ui: new `screens`, `widgets`, `theme`, `tuie_app` modules
- app::recent_commits made pub(crate) for dashboard reuse

Screens: splash (procedural bloom), welcome dashboard, chat (live
streaming), agents picker, settings, plus cron/presence stubs.

Widgets: brand_title, portrait, menu_list, message_list, chat_bubble,
chat_input, cockpit, phase_bar, tool_card, and a reusable `responsive`
container.

Responsive welcome: the welcome screen now offers two viewable modes the
way the old ratatui dashboard did — a side-by-side portrait/stats layout
at >=100 cols and a stacked single column below it — switched by the new
`Responsive` widget. It holds both subtrees and lays out / paints only the
one that fits, while exposing both to id lookups so the menu selection
survives a resize across the breakpoint. Flourishes: a breathing title
colour pulse and a portrait border that surfaces subconscious state.
Covered by a layout test driving a TestTerminal across the breakpoint.
2026-05-30 13:50:52 -04:00

96 lines
4.3 KiB
Rust

//! Atmosphere → tuie Theme mapping.
//!
//! tuie's `harmonious` feature generates a 256-color palette from an 8-color
//! `Theme` struct. We map Souveraine's `ChatPalette` (derived from the active
//! `Atmosphere`) onto tuie's Theme slots so the terminal palette tracks the
//! agent's atmospheric shift — live, without restarting.
use tuie::prelude::Color;
use tuie::theme::Theme;
use crate::ui::atmosphere::Atmosphere;
use crate::ui::chat::ChatPalette;
/// Map a ChatPalette onto tuie's 8-color Theme slots.
///
/// The mapping is approximate but intentional — each role in ChatPalette
/// lands on the Theme slot that best expresses its semantic weight:
///
/// | ChatPalette role | Theme slot | Rationale |
/// |----------------------|-------------|----------------------------------|
/// | `bg` | `bg` | terminal background |
/// | `agent_dim` | `fg` | default foreground / muted text |
/// | `user_accent` | `cyan` | cool, distinct from agent colors |
/// | `tool_accent` | `green` | "go" signal, success |
/// | `agent_primary` | `yellow` | warmth, attention |
/// | `surfacing` | `magenta` | consciousness surfacing |
/// | `compaction` | `red` | urgency, warning |
/// | `reflection` | `blue` | calm, reflective |
pub fn chat_palette_to_theme(palette: &ChatPalette) -> Theme {
Theme {
bg: to_tuie_rgb(palette.bg),
fg: to_tuie_rgb(palette.agent_dim),
cyan: to_tuie_rgb(palette.user_accent),
green: to_tuie_rgb(palette.tool_accent),
yellow: to_tuie_rgb(palette.agent_primary),
magenta: to_tuie_rgb(palette.surfacing),
red: to_tuie_rgb(palette.compaction),
blue: to_tuie_rgb(palette.reflection),
}
}
/// Apply an atmosphere to tuie's global palette.
///
/// Builds a Theme from the atmosphere's ChatPalette, generates the 256-color
/// harmonious palette, and applies it globally. Calls `dirty_layout()` so all
/// widgets re-render on the next frame.
pub fn apply_atmosphere(atm: Atmosphere) {
let palette = ChatPalette::from_atmosphere(atm);
let theme = chat_palette_to_theme(&palette);
tuie::theme::harmonious::apply_palette(
tuie::theme::harmonious::Palette::from_theme(theme),
);
tuie::dirty_layout();
}
/// Convert a ratatui Color to a tuie Rgb.
///
/// tuie uses its own `Rgb` type (in `tuie::util::rgb`) for the Theme struct,
/// while the rest of the widget system uses `tuie::prelude::Color`. This
/// helper bridges ratatui colors (still used by ChatPalette during the dual-
/// stack transition) into tuie's Theme format.
fn to_tuie_rgb(c: ratatui::style::Color) -> tuie::util::rgb::Rgb {
match c {
ratatui::style::Color::Rgb(r, g, b) => tuie::util::rgb::Rgb::new(r, g, b),
_ => tuie::util::rgb::Rgb::new(255, 140, 66), // fallback: Default primary
}
}
/// Convert a ratatui Color to a tuie Color.
///
/// Used when building tuie `Style` objects from `ChatPalette` colors during
/// the transition period. Once ratatui is fully removed, ChatPalette can
/// directly use tuie Color.
pub fn to_tuie_color(c: ratatui::style::Color) -> Color {
match c {
ratatui::style::Color::Rgb(r, g, b) => Color::Rgb(r, g, b),
ratatui::style::Color::Reset => Color::Foreground,
ratatui::style::Color::Black => Color::BLACK,
ratatui::style::Color::Red => Color::RED,
ratatui::style::Color::Green => Color::GREEN,
ratatui::style::Color::Yellow => Color::YELLOW,
ratatui::style::Color::Blue => Color::BLUE,
ratatui::style::Color::Magenta => Color::MAGENTA,
ratatui::style::Color::Cyan => Color::CYAN,
ratatui::style::Color::Gray => Color::BRIGHT_BLACK,
ratatui::style::Color::DarkGray => Color::BRIGHT_BLACK,
ratatui::style::Color::LightRed => Color::BRIGHT_RED,
ratatui::style::Color::LightGreen => Color::BRIGHT_GREEN,
ratatui::style::Color::LightYellow => Color::BRIGHT_YELLOW,
ratatui::style::Color::LightBlue => Color::BRIGHT_BLUE,
ratatui::style::Color::LightMagenta => Color::BRIGHT_MAGENTA,
ratatui::style::Color::LightCyan => Color::BRIGHT_CYAN,
ratatui::style::Color::White => Color::WHITE,
_ => Color::Rgb(255, 140, 66),
}
}