use ratatui::style::{Color, Style, Modifier};
#[derive(Debug, Clone)]
pub struct Theme {
pub name: String,
pub bg_primary: Color,
pub bg_secondary: Color,
pub bg_tertiary: Color,
pub fg_primary: Color,
pub fg_secondary: Color,
pub fg_dim: Color,
pub accent: Color,
pub success: Color,
pub warning: Color,
pub error: Color,
pub info: Color,
pub border: Color,
pub border_focused: Color,
pub selection: Color,
}
impl Theme {
pub fn arc_academy_orange() -> Self {
Self {
name: "Arc Academy Orange".to_string(),
bg_primary: Color::Rgb(18, 18, 20), bg_secondary: Color::Rgb(26, 26, 28), bg_tertiary: Color::Rgb(32, 32, 36),
fg_primary: Color::Rgb(230, 230, 235), fg_secondary: Color::Rgb(180, 180, 190), fg_dim: Color::Rgb(120, 120, 130),
accent: Color::Rgb(255, 107, 53), success: Color::Rgb(80, 200, 120), warning: Color::Rgb(255, 179, 71), error: Color::Rgb(255, 82, 82), info: Color::Rgb(100, 181, 246),
border: Color::Rgb(60, 60, 65), border_focused: Color::Rgb(255, 107, 53), selection: Color::Rgb(80, 50, 35), }
}
pub fn arc_academy_green() -> Self {
Self {
name: "Arc Academy Green".to_string(),
bg_primary: Color::Rgb(16, 20, 18), bg_secondary: Color::Rgb(22, 27, 24), bg_tertiary: Color::Rgb(28, 34, 30),
fg_primary: Color::Rgb(230, 240, 235), fg_secondary: Color::Rgb(180, 200, 190), fg_dim: Color::Rgb(120, 140, 130),
accent: Color::Rgb(76, 175, 80), success: Color::Rgb(102, 187, 106), warning: Color::Rgb(255, 193, 7), error: Color::Rgb(244, 67, 54), info: Color::Rgb(41, 182, 246),
border: Color::Rgb(50, 65, 55), border_focused: Color::Rgb(76, 175, 80), selection: Color::Rgb(30, 50, 35), }
}
pub fn arc_dark() -> Self {
Self {
name: "Arc Dark".to_string(),
bg_primary: Color::Rgb(30, 30, 46), bg_secondary: Color::Rgb(24, 24, 37), bg_tertiary: Color::Rgb(17, 17, 27),
fg_primary: Color::Rgb(205, 214, 244), fg_secondary: Color::Rgb(186, 194, 222), fg_dim: Color::Rgb(108, 112, 134),
accent: Color::Rgb(137, 180, 250), success: Color::Rgb(166, 227, 161), warning: Color::Rgb(249, 226, 175), error: Color::Rgb(243, 139, 168), info: Color::Rgb(148, 226, 213),
border: Color::Rgb(108, 112, 134), border_focused: Color::Rgb(137, 180, 250), selection: Color::Rgb(88, 91, 112), }
}
pub fn arc_light() -> Self {
Self {
name: "Arc Light".to_string(),
bg_primary: Color::Rgb(239, 241, 245), bg_secondary: Color::Rgb(230, 233, 239), bg_tertiary: Color::Rgb(220, 224, 232),
fg_primary: Color::Rgb(76, 79, 105), fg_secondary: Color::Rgb(92, 95, 119), fg_dim: Color::Rgb(156, 160, 176),
accent: Color::Rgb(30, 102, 245), success: Color::Rgb(64, 160, 43), warning: Color::Rgb(223, 142, 29), error: Color::Rgb(210, 15, 57), info: Color::Rgb(4, 165, 229),
border: Color::Rgb(156, 160, 176), border_focused: Color::Rgb(30, 102, 245), selection: Color::Rgb(204, 208, 218), }
}
pub fn style_normal(&self) -> Style {
Style::default().fg(self.fg_primary).bg(self.bg_primary)
}
pub fn style_secondary(&self) -> Style {
Style::default().fg(self.fg_secondary).bg(self.bg_primary)
}
pub fn style_dim(&self) -> Style {
Style::default().fg(self.fg_dim).bg(self.bg_primary)
}
pub fn style_header(&self) -> Style {
Style::default()
.fg(self.fg_primary)
.bg(self.bg_secondary)
.add_modifier(Modifier::BOLD)
}
pub fn style_border_focused(&self) -> Style {
Style::default().fg(self.border_focused)
}
pub fn style_border(&self) -> Style {
Style::default().fg(self.border)
}
pub fn style_accent(&self) -> Style {
Style::default().fg(self.accent).add_modifier(Modifier::BOLD)
}
pub fn style_success(&self) -> Style {
Style::default().fg(self.success)
}
pub fn style_warning(&self) -> Style {
Style::default().fg(self.warning).add_modifier(Modifier::BOLD)
}
pub fn style_error(&self) -> Style {
Style::default().fg(self.error).add_modifier(Modifier::BOLD)
}
pub fn style_info(&self) -> Style {
Style::default().fg(self.info)
}
pub fn style_selection(&self) -> Style {
Style::default()
.bg(self.selection)
.fg(self.fg_primary)
}
pub fn style_block(&self) -> Style {
Style::default().bg(self.bg_primary).fg(self.fg_primary)
}
}
impl Default for Theme {
fn default() -> Self {
Self::arc_academy_orange()
}
}
impl Theme {
pub fn cycle_next(&self) -> Self {
match self.name.as_str() {
"Arc Academy Orange" => Self::arc_academy_green(),
"Arc Academy Green" => Self::arc_dark(),
"Arc Dark" => Self::arc_light(),
_ => Self::arc_academy_orange(),
}
}
pub fn from_name(name: &str) -> Self {
match name {
"Arc Academy Orange" => Self::arc_academy_orange(),
"Arc Academy Green" => Self::arc_academy_green(),
"Arc Dark" => Self::arc_dark(),
"Arc Light" => Self::arc_light(),
_ => {
tracing::warn!("Unknown theme '{}', using default", name);
Self::default()
}
}
}
}