Files
codewhale/crates/tui/src/deepseek_theme.rs
T
Hunter Bown e1ac84ae44 release: v0.6.1 — pricing update, remove light theme + theme setting
- V4 cache-hit input prices cut to 1/10th per DeepSeek pricing update:
  Pro promo 0.03625→0.003625, Pro base 0.145→0.0145, Flash 0.028→0.0028
- Remove the 'light' theme variant (Variant::Light, Theme::light(), test)
- Remove the theme setting entirely — hardcode UI_THEME to whale/dark,
  drop the theme field from Settings, ConfigView, and config command
- Bump workspace version 0.6.0 → 0.6.1 (Cargo.toml, npm pkg, CHANGELOG)
- De-cringe the README: drop emojis, marketing fluff, unverified claims
2026-04-26 11:56:41 -05:00

172 lines
5.8 KiB
Rust

//! Whale/DeepSeek terminal theme tokens.
//!
//! A small, deliberately flat module that names the color, border, and
//! padding choices the TUI is already making. All values match the dark
//! palette previously hard-coded against [`crate::palette`]; a single
//! source-of-truth change here can swap the skin later. Visible output
//! is not changed by introducing this module.
//!
//! The only consumers today are the plan and tool cell renderers in
//! [`crate::tui::history`] and the sidebar section chrome in
//! [`crate::tui::ui`]. All other call sites continue to use [`crate::palette`]
//! directly until they are migrated in a later slice.
use ratatui::style::{Color, Modifier, Style};
use ratatui::widgets::{BorderType, Borders, Padding};
use crate::palette;
use crate::tui::history::ToolStatus;
/// Visual variant exposed by the theme.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Variant {
Dark,
}
/// Centralized visual tokens for sidebar, plan, and tool rendering.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct Theme {
pub variant: Variant,
// Sidebar / section chrome
pub section_borders: Borders,
pub section_border_type: BorderType,
pub section_border_color: Color,
pub section_bg: Color,
pub section_title_color: Color,
pub section_padding: Padding,
// Tool cell color tokens
pub tool_title_color: Color,
pub tool_value_color: Color,
pub tool_label_color: Color,
pub tool_running_accent: Color,
pub tool_success_accent: Color,
pub tool_failed_accent: Color,
// Plan cell color tokens
pub plan_progress_color: Color,
pub plan_summary_color: Color,
pub plan_explanation_color: Color,
pub plan_pending_color: Color,
pub plan_in_progress_color: Color,
pub plan_completed_color: Color,
}
impl Theme {
/// The current dark theme. Visible output today uses these values.
#[must_use]
pub const fn dark() -> Self {
Self {
variant: Variant::Dark,
section_borders: Borders::ALL,
section_border_type: BorderType::Plain,
section_border_color: palette::BORDER_COLOR,
section_bg: palette::DEEPSEEK_INK,
section_title_color: palette::DEEPSEEK_BLUE,
section_padding: Padding::uniform(1),
tool_title_color: palette::TEXT_SOFT,
tool_value_color: palette::TEXT_MUTED,
tool_label_color: palette::TEXT_DIM,
tool_running_accent: palette::ACCENT_TOOL_LIVE,
tool_success_accent: palette::TEXT_DIM,
tool_failed_accent: palette::ACCENT_TOOL_ISSUE,
plan_progress_color: palette::STATUS_SUCCESS,
plan_summary_color: palette::TEXT_MUTED,
plan_explanation_color: palette::TEXT_DIM,
plan_pending_color: palette::TEXT_MUTED,
plan_in_progress_color: palette::STATUS_WARNING,
plan_completed_color: palette::STATUS_SUCCESS,
}
}
/// Pick the right tool accent for a given [`ToolStatus`].
#[must_use]
pub const fn tool_status_color(self, status: ToolStatus) -> Color {
match status {
ToolStatus::Running => self.tool_running_accent,
ToolStatus::Success => self.tool_success_accent,
ToolStatus::Failed => self.tool_failed_accent,
}
}
/// Bold tool title style (e.g. "Plan", "Shell").
#[must_use]
pub fn tool_title_style(self) -> Style {
Style::default()
.fg(self.tool_title_color)
.add_modifier(Modifier::BOLD)
}
/// Right-side status text ("running", "done", "issue") style.
#[must_use]
pub fn tool_status_style(self, status: ToolStatus) -> Style {
Style::default().fg(self.tool_status_color(status))
}
/// Detail label style ("command:", "time:", step markers).
#[must_use]
pub fn tool_label_style(self) -> Style {
Style::default().fg(self.tool_label_color)
}
/// Default value style for tool detail rows.
#[must_use]
pub fn tool_value_style(self) -> Style {
Style::default().fg(self.tool_value_color)
}
}
/// Returns the active theme used by the TUI today.
///
/// Today this is always `Theme::dark()`. A future PR can wire this to an
/// `App` field or a config setting in five lines.
#[must_use]
pub const fn active_theme() -> Theme {
Theme::dark()
}
#[cfg(test)]
mod tests {
use super::{Theme, Variant, active_theme};
use crate::palette;
use crate::tui::history::ToolStatus;
#[test]
fn active_theme_returns_dark() {
assert_eq!(active_theme(), Theme::dark());
}
#[test]
fn dark_theme_matches_existing_palette_choices() {
let theme = Theme::dark();
assert_eq!(theme.variant, Variant::Dark);
assert_eq!(theme.section_border_color, palette::BORDER_COLOR);
assert_eq!(theme.section_bg, palette::DEEPSEEK_INK);
assert_eq!(theme.section_title_color, palette::DEEPSEEK_BLUE);
assert_eq!(theme.tool_title_color, palette::TEXT_SOFT);
assert_eq!(theme.tool_value_color, palette::TEXT_MUTED);
assert_eq!(theme.tool_label_color, palette::TEXT_DIM);
assert_eq!(theme.tool_running_accent, palette::ACCENT_TOOL_LIVE);
assert_eq!(theme.tool_success_accent, palette::TEXT_DIM);
assert_eq!(theme.tool_failed_accent, palette::ACCENT_TOOL_ISSUE);
}
#[test]
fn tool_status_color_maps_each_status() {
let theme = Theme::dark();
assert_eq!(
theme.tool_status_color(ToolStatus::Running),
theme.tool_running_accent
);
assert_eq!(
theme.tool_status_color(ToolStatus::Success),
theme.tool_success_accent
);
assert_eq!(
theme.tool_status_color(ToolStatus::Failed),
theme.tool_failed_accent
);
}
}