use ratatui::style::{Color, Modifier, Style};
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum Theme {
#[default]
Default,
Dracula,
SolarizedDark,
Nord,
GruvboxDark,
GithubLight,
}
impl Theme {
pub const ALL: &'static [Theme] = &[
Theme::Default,
Theme::Dracula,
Theme::SolarizedDark,
Theme::Nord,
Theme::GruvboxDark,
Theme::GithubLight,
];
pub fn label(self) -> &'static str {
match self {
Theme::Default => "Default",
Theme::Dracula => "Dracula",
Theme::SolarizedDark => "Solarized Dark",
Theme::Nord => "Nord",
Theme::GruvboxDark => "Gruvbox Dark",
Theme::GithubLight => "GitHub Light",
}
}
}
#[derive(Debug, Clone, Copy)]
pub struct Palette {
pub background: Color,
pub foreground: Color,
pub dim: Color,
pub border: Color,
pub border_focused: Color,
pub accent: Color,
pub accent_alt: Color,
pub selection_bg: Color,
pub selection_fg: Color,
pub title: Color,
pub h1: Color,
pub h2: Color,
pub h3: Color,
pub heading_other: Color,
pub inline_code: Color,
pub code_fg: Color,
pub code_bg: Color,
pub code_border: Color,
pub link: Color,
pub list_marker: Color,
pub task_marker: Color,
pub block_quote_fg: Color,
pub block_quote_border: Color,
pub table_header: Color,
pub table_border: Color,
pub search_match_bg: Color,
pub current_match_bg: Color,
pub match_fg: Color,
pub gutter: Color,
pub status_bar_bg: Color,
pub status_bar_fg: Color,
pub help_bg: Color,
}
impl Palette {
pub fn from_theme(theme: Theme) -> Self {
match theme {
Theme::Default => Self {
background: Color::Rgb(20, 20, 30),
foreground: Color::Rgb(220, 220, 220),
dim: Color::DarkGray,
border: Color::DarkGray,
border_focused: Color::Cyan,
accent: Color::Cyan,
accent_alt: Color::Yellow,
selection_bg: Color::Rgb(0, 160, 80),
selection_fg: Color::Black,
title: Color::Rgb(220, 220, 220),
h1: Color::Cyan,
h2: Color::Blue,
h3: Color::Magenta,
heading_other: Color::White,
inline_code: Color::Green,
code_fg: Color::Rgb(180, 200, 180),
code_bg: Color::Rgb(40, 40, 40),
code_border: Color::DarkGray,
link: Color::Blue,
list_marker: Color::Yellow,
task_marker: Color::Cyan,
block_quote_fg: Color::Gray,
block_quote_border: Color::DarkGray,
table_header: Color::Cyan,
table_border: Color::DarkGray,
search_match_bg: Color::Yellow,
current_match_bg: Color::Rgb(255, 120, 0),
match_fg: Color::Black,
gutter: Color::DarkGray,
status_bar_bg: Color::Rgb(30, 30, 30),
status_bar_fg: Color::Gray,
help_bg: Color::Rgb(20, 20, 30),
},
Theme::Dracula => Self {
background: Color::Rgb(40, 42, 54), foreground: Color::Rgb(248, 248, 242), dim: Color::Rgb(98, 114, 164), border: Color::Rgb(68, 71, 90), border_focused: Color::Rgb(189, 147, 249), accent: Color::Rgb(189, 147, 249), accent_alt: Color::Rgb(241, 250, 140), selection_bg: Color::Rgb(68, 71, 90), selection_fg: Color::Rgb(248, 248, 242),
title: Color::Rgb(248, 248, 242),
h1: Color::Rgb(255, 121, 198), h2: Color::Rgb(189, 147, 249), h3: Color::Rgb(80, 250, 123), heading_other: Color::Rgb(248, 248, 242),
inline_code: Color::Rgb(80, 250, 123), code_fg: Color::Rgb(248, 248, 242),
code_bg: Color::Rgb(40, 42, 54),
code_border: Color::Rgb(98, 114, 164),
link: Color::Rgb(139, 233, 253), list_marker: Color::Rgb(241, 250, 140), task_marker: Color::Rgb(80, 250, 123), block_quote_fg: Color::Rgb(98, 114, 164),
block_quote_border: Color::Rgb(98, 114, 164),
table_header: Color::Rgb(255, 121, 198), table_border: Color::Rgb(98, 114, 164),
search_match_bg: Color::Rgb(241, 250, 140), current_match_bg: Color::Rgb(255, 121, 198), match_fg: Color::Rgb(40, 42, 54),
gutter: Color::Rgb(98, 114, 164),
status_bar_bg: Color::Rgb(40, 42, 54),
status_bar_fg: Color::Rgb(98, 114, 164),
help_bg: Color::Rgb(40, 42, 54),
},
Theme::SolarizedDark => Self {
background: Color::Rgb(0, 43, 54), foreground: Color::Rgb(131, 148, 150), dim: Color::Rgb(88, 110, 117), border: Color::Rgb(88, 110, 117), border_focused: Color::Rgb(38, 139, 210), accent: Color::Rgb(38, 139, 210), accent_alt: Color::Rgb(181, 137, 0), selection_bg: Color::Rgb(7, 54, 66), selection_fg: Color::Rgb(147, 161, 161), title: Color::Rgb(147, 161, 161), h1: Color::Rgb(203, 75, 22), h2: Color::Rgb(38, 139, 210), h3: Color::Rgb(42, 161, 152), heading_other: Color::Rgb(131, 148, 150),
inline_code: Color::Rgb(133, 153, 0), code_fg: Color::Rgb(131, 148, 150),
code_bg: Color::Rgb(7, 54, 66), code_border: Color::Rgb(88, 110, 117),
link: Color::Rgb(38, 139, 210), list_marker: Color::Rgb(181, 137, 0), task_marker: Color::Rgb(42, 161, 152), block_quote_fg: Color::Rgb(88, 110, 117),
block_quote_border: Color::Rgb(88, 110, 117),
table_header: Color::Rgb(203, 75, 22), table_border: Color::Rgb(88, 110, 117),
search_match_bg: Color::Rgb(181, 137, 0), current_match_bg: Color::Rgb(203, 75, 22), match_fg: Color::Rgb(0, 43, 54),
gutter: Color::Rgb(88, 110, 117),
status_bar_bg: Color::Rgb(7, 54, 66),
status_bar_fg: Color::Rgb(88, 110, 117),
help_bg: Color::Rgb(7, 54, 66),
},
Theme::Nord => Self {
background: Color::Rgb(46, 52, 64), foreground: Color::Rgb(216, 222, 233), dim: Color::Rgb(76, 86, 106), border: Color::Rgb(67, 76, 94), border_focused: Color::Rgb(136, 192, 208), accent: Color::Rgb(136, 192, 208), accent_alt: Color::Rgb(235, 203, 139), selection_bg: Color::Rgb(67, 76, 94), selection_fg: Color::Rgb(236, 239, 244), title: Color::Rgb(236, 239, 244), h1: Color::Rgb(191, 97, 106), h2: Color::Rgb(136, 192, 208), h3: Color::Rgb(163, 190, 140), heading_other: Color::Rgb(216, 222, 233),
inline_code: Color::Rgb(163, 190, 140), code_fg: Color::Rgb(216, 222, 233),
code_bg: Color::Rgb(59, 66, 82), code_border: Color::Rgb(76, 86, 106),
link: Color::Rgb(129, 161, 193), list_marker: Color::Rgb(235, 203, 139), task_marker: Color::Rgb(163, 190, 140), block_quote_fg: Color::Rgb(76, 86, 106),
block_quote_border: Color::Rgb(76, 86, 106),
table_header: Color::Rgb(94, 129, 172), table_border: Color::Rgb(76, 86, 106),
search_match_bg: Color::Rgb(235, 203, 139), current_match_bg: Color::Rgb(191, 97, 106), match_fg: Color::Rgb(46, 52, 64),
gutter: Color::Rgb(76, 86, 106),
status_bar_bg: Color::Rgb(59, 66, 82),
status_bar_fg: Color::Rgb(76, 86, 106),
help_bg: Color::Rgb(59, 66, 82),
},
Theme::GruvboxDark => Self {
background: Color::Rgb(40, 40, 40), foreground: Color::Rgb(235, 219, 178), dim: Color::Rgb(146, 131, 116), border: Color::Rgb(80, 73, 69), border_focused: Color::Rgb(214, 93, 14), accent: Color::Rgb(250, 189, 47), accent_alt: Color::Rgb(184, 187, 38), selection_bg: Color::Rgb(80, 73, 69), selection_fg: Color::Rgb(235, 219, 178),
title: Color::Rgb(235, 219, 178),
h1: Color::Rgb(251, 73, 52), h2: Color::Rgb(250, 189, 47), h3: Color::Rgb(184, 187, 38), heading_other: Color::Rgb(235, 219, 178),
inline_code: Color::Rgb(184, 187, 38), code_fg: Color::Rgb(235, 219, 178),
code_bg: Color::Rgb(50, 48, 47), code_border: Color::Rgb(80, 73, 69),
link: Color::Rgb(131, 165, 152), list_marker: Color::Rgb(250, 189, 47), task_marker: Color::Rgb(184, 187, 38), block_quote_fg: Color::Rgb(146, 131, 116),
block_quote_border: Color::Rgb(146, 131, 116),
table_header: Color::Rgb(214, 93, 14), table_border: Color::Rgb(80, 73, 69),
search_match_bg: Color::Rgb(250, 189, 47), current_match_bg: Color::Rgb(251, 73, 52), match_fg: Color::Rgb(40, 40, 40),
gutter: Color::Rgb(102, 92, 84), status_bar_bg: Color::Rgb(50, 48, 47),
status_bar_fg: Color::Rgb(146, 131, 116),
help_bg: Color::Rgb(50, 48, 47),
},
Theme::GithubLight => Self {
background: Color::Rgb(255, 255, 255), foreground: Color::Rgb(31, 35, 40), dim: Color::Rgb(101, 109, 118), border: Color::Rgb(208, 215, 222), border_focused: Color::Rgb(9, 105, 218), accent: Color::Rgb(9, 105, 218), accent_alt: Color::Rgb(130, 80, 0), selection_bg: Color::Rgb(9, 105, 218), selection_fg: Color::Rgb(255, 255, 255),
title: Color::Rgb(31, 35, 40),
h1: Color::Rgb(9, 105, 218), h2: Color::Rgb(130, 80, 0), h3: Color::Rgb(26, 127, 55), heading_other: Color::Rgb(31, 35, 40),
inline_code: Color::Rgb(207, 34, 46), code_fg: Color::Rgb(31, 35, 40),
code_bg: Color::Rgb(246, 248, 250), code_border: Color::Rgb(208, 215, 222),
link: Color::Rgb(9, 105, 218),
list_marker: Color::Rgb(130, 80, 0),
task_marker: Color::Rgb(26, 127, 55),
block_quote_fg: Color::Rgb(101, 109, 118),
block_quote_border: Color::Rgb(208, 215, 222),
table_header: Color::Rgb(9, 105, 218),
table_border: Color::Rgb(208, 215, 222),
search_match_bg: Color::Rgb(255, 218, 9), current_match_bg: Color::Rgb(255, 143, 0),
match_fg: Color::Rgb(31, 35, 40),
gutter: Color::Rgb(101, 109, 118),
status_bar_bg: Color::Rgb(246, 248, 250),
status_bar_fg: Color::Rgb(101, 109, 118),
help_bg: Color::Rgb(246, 248, 250),
},
}
}
pub fn border_style(self) -> Style {
Style::new().fg(self.border)
}
pub fn border_focused_style(self) -> Style {
Style::new().fg(self.border_focused)
}
pub fn title_style(self) -> Style {
Style::new().fg(self.title).add_modifier(Modifier::BOLD)
}
pub fn selected_style(self) -> Style {
Style::new()
.bg(self.selection_bg)
.fg(self.selection_fg)
.add_modifier(Modifier::BOLD)
}
pub fn dim_style(self) -> Style {
Style::new().fg(self.dim)
}
}
impl Default for Palette {
fn default() -> Self {
Self::from_theme(Theme::Default)
}
}