From 7a9cb7bf342367c81fb4a1568675e46f132a8afc Mon Sep 17 00:00:00 2001 From: asepharyana Date: Tue, 14 Jul 2026 12:18:13 +0700 Subject: [PATCH] feat(tui): ganti palet warna ke Tokyo Night Co-Authored-By: Claude Sonnet 5 --- src/view/theme.rs | 102 ++++++++++++++++++++++++---------------------- 1 file changed, 54 insertions(+), 48 deletions(-) diff --git a/src/view/theme.rs b/src/view/theme.rs index 7ee93b2..d1eed9b 100644 --- a/src/view/theme.rs +++ b/src/view/theme.rs @@ -1,13 +1,13 @@ -//! Central color theme for the TUI — modern dark palette with neon accents. +//! Central color theme for the TUI — Tokyo Night palette. //! //! Flow: defines a single `Theme` marker struct with associated `Color` //! consts, consumed by every `view/*` render function so styling stays //! consistent and changeable from one place. //! -//! Design: dark-primary background (#1a1b26 / Catppuccin Mocha inspired), -//! vibrant accent colors for semantic states, and muted tones for -//! secondary/background elements. This gives a modern "neon dashboard" -//! look that is easy on the eyes during long sessions. +//! Design: muted blue-purple dark background with desaturated blue/cyan/ +//! purple accents (not neon) — the popular Tokyo Night editor/terminal +//! theme. Chosen for a calmer "professional dev tool" read in place of +//! the previous neon-accented palette. use ratatui::style::Color; @@ -20,75 +20,81 @@ pub struct Theme; impl Theme { // ── Base surface colors ────────────────────────────────────────────── /// Deep background — used for the main chat area and overlays. - pub const BG: Color = Color::Rgb(24, 25, 38); + pub const BG: Color = Color::Rgb(0x1a, 0x1b, 0x26); /// Slightly lighter surface — for panels, cards, and input bars. - pub const SURFACE: Color = Color::Rgb(30, 32, 48); + pub const SURFACE: Color = Color::Rgb(0x1f, 0x23, 0x35); /// Elevated surface — for dropdowns, toasts, and floating elements. - pub const SURFACE_ELEVATED: Color = Color::Rgb(38, 40, 58); + pub const SURFACE_ELEVATED: Color = Color::Rgb(0x29, 0x2e, 0x42); // ── Text colors ────────────────────────────────────────────────────── - /// Primary text color (bright white). - pub const TEXT: Color = Color::Rgb(220, 222, 245); + /// Primary text color. + pub const TEXT: Color = Color::Rgb(0xc0, 0xca, 0xf5); /// Secondary / muted text. - pub const TEXT_MUTED: Color = Color::Rgb(150, 152, 180); + pub const TEXT_MUTED: Color = Color::Rgb(0xa9, 0xb1, 0xd6); /// Dim / placeholder text. - pub const TEXT_DIM: Color = Color::Rgb(90, 92, 120); + pub const TEXT_DIM: Color = Color::Rgb(0x56, 0x5f, 0x89); // ── Accent colors ──────────────────────────────────────────────────── - /// Primary accent — cyan for borders, titles, selections. - pub const PRIMARY: Color = Color::Rgb(0, 212, 255); + /// Primary accent — blue for borders, titles, selections. + pub const PRIMARY: Color = Color::Rgb(0x7a, 0xa2, 0xf7); /// Success / positive states — green. - pub const SUCCESS: Color = Color::Rgb(80, 220, 130); - /// Warning / in-progress states — yellow-orange. - pub const WARNING: Color = Color::Rgb(255, 200, 80); + pub const SUCCESS: Color = Color::Rgb(0x9e, 0xce, 0x6a); + /// Warning / in-progress states — yellow. + pub const WARNING: Color = Color::Rgb(0xe0, 0xaf, 0x68); /// Error / failure states — red. - pub const ERROR: Color = Color::Rgb(255, 100, 110); - /// Informational / neutral — blue. - pub const INFO: Color = Color::Rgb(100, 170, 255); + pub const ERROR: Color = Color::Rgb(0xf7, 0x76, 0x8e); + /// Informational / neutral — cyan. + pub const INFO: Color = Color::Rgb(0x7d, 0xcf, 0xff); // ── Extended accent palette ────────────────────────────────────────── /// Purple accent — used for special highlights. - pub const ACCENT_PURPLE: Color = Color::Rgb(180, 130, 255); - #[allow(dead_code)] - /// Pink / magenta accent. - pub const ACCENT_PINK: Color = Color::Rgb(255, 120, 200); + pub const ACCENT_PURPLE: Color = Color::Rgb(0xbb, 0x9a, 0xf7); /// Orange accent. - pub const ACCENT_ORANGE: Color = Color::Rgb(255, 160, 60); + pub const ACCENT_ORANGE: Color = Color::Rgb(0xff, 0x9e, 0x64); /// Teal accent. - pub const ACCENT_TEAL: Color = Color::Rgb(60, 210, 200); + pub const ACCENT_TEAL: Color = Color::Rgb(0x73, 0xda, 0xca); // ── Border colors ──────────────────────────────────────────────────── /// Standard border color. - pub const BORDER: Color = Color::Rgb(50, 52, 72); - #[allow(dead_code)] - /// Focused / active border. - pub const BORDER_FOCUS: Color = Color::Rgb(0, 180, 220); + pub const BORDER: Color = Color::Rgb(0x3b, 0x42, 0x61); // ── Role badge colors ──────────────────────────────────────────────── - pub const ROLE_USER: Color = Color::Rgb(80, 220, 130); // green - pub const ROLE_ASSISTANT: Color = Color::Rgb(0, 212, 255); // cyan - pub const ROLE_SYSTEM: Color = Color::Rgb(100, 170, 255); // blue - pub const ROLE_TOOL: Color = Color::Rgb(255, 200, 80); // yellow + pub const ROLE_USER: Color = Color::Rgb(0x9e, 0xce, 0x6a); // green + pub const ROLE_ASSISTANT: Color = Color::Rgb(0x7a, 0xa2, 0xf7); // blue + pub const ROLE_SYSTEM: Color = Color::Rgb(0x7d, 0xcf, 0xff); // cyan + pub const ROLE_TOOL: Color = Color::Rgb(0xe0, 0xaf, 0x68); // yellow // ── Status colors ──────────────────────────────────────────────────── - pub const STATUS_BAR_BG: Color = Color::Rgb(20, 21, 34); - pub const MODE_AUTO: Color = Color::Rgb(80, 220, 130); - pub const MODE_YOLO: Color = Color::Rgb(255, 100, 110); + pub const STATUS_BAR_BG: Color = Color::Rgb(0x16, 0x16, 0x1e); + pub const MODE_AUTO: Color = Color::Rgb(0x9e, 0xce, 0x6a); + pub const MODE_YOLO: Color = Color::Rgb(0xf7, 0x76, 0x8e); // ── Code / markdown ────────────────────────────────────────────────── - pub const CODE_BG: Color = Color::Rgb(20, 22, 35); - pub const CODE_BAR: Color = Color::Rgb(40, 42, 62); - pub const BLOCKQUOTE_BAR: Color = Color::Rgb(100, 170, 255); + pub const CODE_BG: Color = Color::Rgb(0x16, 0x16, 0x1e); + pub const CODE_BAR: Color = Color::Rgb(0x29, 0x2e, 0x42); + pub const BLOCKQUOTE_BAR: Color = Color::Rgb(0x7d, 0xcf, 0xff); // ── Misc ───────────────────────────────────────────────────────────── /// Highlight / selection background. - pub const HIGHLIGHT: Color = Color::Rgb(0, 140, 180); + pub const HIGHLIGHT: Color = Color::Rgb(0x3d, 0x59, 0xa1); /// Dim highlight (for non-selected items). - pub const HIGHLIGHT_DIM: Color = Color::Rgb(30, 40, 60); - #[allow(dead_code)] - /// Scrollbar track. - pub const SCROLLBAR_BG: Color = Color::Rgb(35, 37, 55); - #[allow(dead_code)] - /// Scrollbar thumb. - pub const SCROLLBAR_FG: Color = Color::Rgb(60, 62, 85); + pub const HIGHLIGHT_DIM: Color = Color::Rgb(0x29, 0x2e, 0x42); +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn palette_matches_tokyo_night_spec() { + assert_eq!(Theme::BG, Color::Rgb(0x1a, 0x1b, 0x26)); + assert_eq!(Theme::SURFACE, Color::Rgb(0x1f, 0x23, 0x35)); + assert_eq!(Theme::PRIMARY, Color::Rgb(0x7a, 0xa2, 0xf7)); + assert_eq!(Theme::SUCCESS, Color::Rgb(0x9e, 0xce, 0x6a)); + assert_eq!(Theme::WARNING, Color::Rgb(0xe0, 0xaf, 0x68)); + assert_eq!(Theme::ERROR, Color::Rgb(0xf7, 0x76, 0x8e)); + assert_eq!(Theme::INFO, Color::Rgb(0x7d, 0xcf, 0xff)); + assert_eq!(Theme::ACCENT_PURPLE, Color::Rgb(0xbb, 0x9a, 0xf7)); + assert_eq!(Theme::BORDER, Color::Rgb(0x3b, 0x42, 0x61)); + } }