use ratatui::style::Color;
pub const C_BRAND: Color = Color::Rgb(255, 100, 30);
pub const C_ACCENT: Color = Color::Rgb(80, 200, 255);
pub const C_SUCCESS: Color = Color::Rgb(80, 220, 120);
pub const C_DIM: Color = Color::Rgb(120, 120, 130);
pub const C_FG: Color = Color::White;
pub const C_SEL_BG: Color = Color::Rgb(40, 60, 80);
pub const C_DIR: Color = Color::Rgb(255, 210, 80);
pub const C_MATCH: Color = Color::Rgb(80, 220, 120);
#[derive(Debug, Clone, PartialEq)]
pub struct Theme {
pub brand: Color,
pub accent: Color,
pub success: Color,
pub dim: Color,
pub fg: Color,
pub sel_bg: Color,
pub dir: Color,
pub match_file: Color,
}
impl Default for Theme {
fn default() -> Self {
Self {
brand: C_BRAND,
accent: C_ACCENT,
success: C_SUCCESS,
dim: C_DIM,
fg: C_FG,
sel_bg: C_SEL_BG,
dir: C_DIR,
match_file: C_MATCH,
}
}
}
impl Theme {
pub fn new() -> Self {
Self::default()
}
pub fn brand(mut self, color: Color) -> Self {
self.brand = color;
self
}
pub fn accent(mut self, color: Color) -> Self {
self.accent = color;
self
}
pub fn success(mut self, color: Color) -> Self {
self.success = color;
self
}
pub fn dim(mut self, color: Color) -> Self {
self.dim = color;
self
}
pub fn fg(mut self, color: Color) -> Self {
self.fg = color;
self
}
pub fn sel_bg(mut self, color: Color) -> Self {
self.sel_bg = color;
self
}
pub fn dir(mut self, color: Color) -> Self {
self.dir = color;
self
}
pub fn match_file(mut self, color: Color) -> Self {
self.match_file = color;
self
}
}
impl Theme {
pub fn dracula() -> Self {
Self {
brand: Color::Rgb(255, 121, 198), accent: Color::Rgb(139, 233, 253), dir: Color::Rgb(241, 250, 140), sel_bg: Color::Rgb(68, 71, 90), success: Color::Rgb(80, 250, 123), match_file: Color::Rgb(80, 250, 123), dim: Color::Rgb(98, 114, 164), fg: Color::Rgb(248, 248, 242), }
}
pub fn nord() -> Self {
Self {
brand: Color::Rgb(136, 192, 208), accent: Color::Rgb(129, 161, 193), dir: Color::Rgb(235, 203, 139), sel_bg: Color::Rgb(59, 66, 82), success: Color::Rgb(163, 190, 140), match_file: Color::Rgb(163, 190, 140), dim: Color::Rgb(76, 86, 106), fg: Color::Rgb(216, 222, 233), }
}
pub fn solarized_dark() -> Self {
Self {
brand: Color::Rgb(38, 139, 210), accent: Color::Rgb(42, 161, 152), dir: Color::Rgb(181, 137, 0), sel_bg: Color::Rgb(7, 54, 66), success: Color::Rgb(133, 153, 0), match_file: Color::Rgb(133, 153, 0), dim: Color::Rgb(88, 110, 117), fg: Color::Rgb(131, 148, 150), }
}
pub fn solarized_light() -> Self {
Self {
brand: Color::Rgb(38, 139, 210), accent: Color::Rgb(42, 161, 152), dir: Color::Rgb(181, 137, 0), sel_bg: Color::Rgb(238, 232, 213), success: Color::Rgb(133, 153, 0), match_file: Color::Rgb(0, 110, 100), dim: Color::Rgb(147, 161, 161), fg: Color::Rgb(101, 123, 131), }
}
pub fn gruvbox_dark() -> Self {
Self {
brand: Color::Rgb(254, 128, 25), accent: Color::Rgb(250, 189, 47), dir: Color::Rgb(250, 189, 47), sel_bg: Color::Rgb(60, 56, 54), success: Color::Rgb(184, 187, 38), match_file: Color::Rgb(142, 192, 124), dim: Color::Rgb(146, 131, 116), fg: Color::Rgb(235, 219, 178), }
}
pub fn gruvbox_light() -> Self {
Self {
brand: Color::Rgb(214, 93, 14), accent: Color::Rgb(215, 153, 33), dir: Color::Rgb(181, 118, 20), sel_bg: Color::Rgb(213, 196, 161), success: Color::Rgb(121, 116, 14), match_file: Color::Rgb(104, 157, 106), dim: Color::Rgb(146, 131, 116), fg: Color::Rgb(60, 56, 54), }
}
pub fn catppuccin_latte() -> Self {
Self {
brand: Color::Rgb(136, 57, 239), accent: Color::Rgb(30, 102, 245), dir: Color::Rgb(254, 100, 11), sel_bg: Color::Rgb(204, 208, 218), success: Color::Rgb(64, 160, 43), match_file: Color::Rgb(23, 146, 153), dim: Color::Rgb(156, 160, 176), fg: Color::Rgb(76, 79, 105), }
}
pub fn catppuccin_frappe() -> Self {
Self {
brand: Color::Rgb(202, 158, 230), accent: Color::Rgb(140, 170, 238), dir: Color::Rgb(229, 200, 144), sel_bg: Color::Rgb(65, 69, 89), success: Color::Rgb(166, 209, 137), match_file: Color::Rgb(129, 200, 190), dim: Color::Rgb(115, 121, 148), fg: Color::Rgb(198, 208, 245), }
}
pub fn catppuccin_macchiato() -> Self {
Self {
brand: Color::Rgb(198, 160, 246), accent: Color::Rgb(138, 173, 244), dir: Color::Rgb(238, 212, 159), sel_bg: Color::Rgb(54, 58, 79), success: Color::Rgb(166, 218, 149), match_file: Color::Rgb(139, 213, 202), dim: Color::Rgb(110, 115, 141), fg: Color::Rgb(202, 211, 245), }
}
pub fn catppuccin_mocha() -> Self {
Self {
brand: Color::Rgb(203, 166, 247), accent: Color::Rgb(137, 180, 250), dir: Color::Rgb(249, 226, 175), sel_bg: Color::Rgb(49, 50, 68), success: Color::Rgb(166, 227, 161), match_file: Color::Rgb(148, 226, 213), dim: Color::Rgb(108, 112, 134), fg: Color::Rgb(205, 214, 244), }
}
pub fn tokyo_night() -> Self {
Self {
brand: Color::Rgb(187, 154, 247), accent: Color::Rgb(122, 162, 247), dir: Color::Rgb(224, 175, 104), sel_bg: Color::Rgb(41, 46, 66), success: Color::Rgb(158, 206, 106), match_file: Color::Rgb(115, 218, 202), dim: Color::Rgb(86, 95, 137), fg: Color::Rgb(192, 202, 245), }
}
pub fn tokyo_night_storm() -> Self {
Self {
brand: Color::Rgb(187, 154, 247), accent: Color::Rgb(122, 162, 247), dir: Color::Rgb(224, 175, 104), sel_bg: Color::Rgb(45, 49, 75), success: Color::Rgb(158, 206, 106), match_file: Color::Rgb(115, 218, 202), dim: Color::Rgb(86, 95, 137), fg: Color::Rgb(192, 202, 245), }
}
pub fn tokyo_night_light() -> Self {
Self {
brand: Color::Rgb(90, 74, 120), accent: Color::Rgb(46, 126, 233), dir: Color::Rgb(140, 108, 62), sel_bg: Color::Rgb(208, 213, 227), success: Color::Rgb(72, 94, 48), match_file: Color::Rgb(15, 75, 110), dim: Color::Rgb(132, 140, 176), fg: Color::Rgb(52, 59, 88), }
}
pub fn kanagawa_wave() -> Self {
Self {
brand: Color::Rgb(210, 126, 153), accent: Color::Rgb(126, 156, 216), dir: Color::Rgb(220, 165, 97), sel_bg: Color::Rgb(42, 42, 55), success: Color::Rgb(118, 148, 106), match_file: Color::Rgb(106, 149, 137), dim: Color::Rgb(114, 113, 105), fg: Color::Rgb(220, 215, 186), }
}
pub fn kanagawa_dragon() -> Self {
Self {
brand: Color::Rgb(210, 126, 153), accent: Color::Rgb(139, 164, 176), dir: Color::Rgb(200, 170, 109), sel_bg: Color::Rgb(40, 39, 39), success: Color::Rgb(135, 169, 135), match_file: Color::Rgb(142, 164, 162), dim: Color::Rgb(166, 166, 156), fg: Color::Rgb(197, 201, 197), }
}
pub fn kanagawa_lotus() -> Self {
Self {
brand: Color::Rgb(160, 154, 190), accent: Color::Rgb(77, 105, 155), dir: Color::Rgb(119, 113, 63), sel_bg: Color::Rgb(231, 219, 160), success: Color::Rgb(111, 137, 78), match_file: Color::Rgb(78, 140, 162), dim: Color::Rgb(196, 178, 138), fg: Color::Rgb(84, 84, 100), }
}
pub fn moonfly() -> Self {
Self {
brand: Color::Rgb(174, 129, 255), accent: Color::Rgb(128, 160, 255), dir: Color::Rgb(227, 199, 138), sel_bg: Color::Rgb(28, 28, 28), success: Color::Rgb(140, 200, 95), match_file: Color::Rgb(121, 219, 195), dim: Color::Rgb(78, 78, 78), fg: Color::Rgb(178, 178, 178), }
}
pub fn nightfly() -> Self {
Self {
brand: Color::Rgb(199, 146, 234), accent: Color::Rgb(130, 170, 255), dir: Color::Rgb(255, 202, 40), sel_bg: Color::Rgb(11, 41, 66), success: Color::Rgb(161, 205, 94), match_file: Color::Rgb(33, 199, 168), dim: Color::Rgb(75, 100, 121), fg: Color::Rgb(172, 187, 203), }
}
pub fn oxocarbon() -> Self {
Self {
brand: Color::Rgb(255, 126, 182), accent: Color::Rgb(120, 169, 255), dir: Color::Rgb(255, 213, 0), sel_bg: Color::Rgb(38, 38, 38), success: Color::Rgb(66, 190, 101), match_file: Color::Rgb(51, 177, 255), dim: Color::Rgb(82, 82, 82), fg: Color::Rgb(242, 244, 248), }
}
pub fn grape() -> Self {
Self::default()
.brand(Color::Rgb(200, 120, 255))
.accent(Color::Rgb(130, 180, 255))
.dir(Color::Rgb(200, 160, 255))
.sel_bg(Color::Rgb(50, 35, 80))
.success(Color::Rgb(160, 110, 255))
.match_file(Color::Rgb(180, 130, 255))
.dim(Color::Rgb(110, 100, 130))
}
pub fn ocean() -> Self {
Self::default()
.brand(Color::Rgb(0, 200, 180))
.accent(Color::Rgb(0, 175, 210))
.dir(Color::Rgb(100, 220, 210))
.sel_bg(Color::Rgb(0, 50, 70))
.success(Color::Rgb(80, 230, 200))
.match_file(Color::Rgb(80, 230, 200))
.dim(Color::Rgb(80, 120, 130))
.fg(Color::Rgb(200, 240, 245))
}
pub fn sunset() -> Self {
Self::default()
.brand(Color::Rgb(255, 80, 80))
.accent(Color::Rgb(255, 150, 50))
.dir(Color::Rgb(255, 200, 60))
.sel_bg(Color::Rgb(80, 30, 20))
.success(Color::Rgb(255, 180, 80))
.match_file(Color::Rgb(255, 180, 80))
.dim(Color::Rgb(140, 100, 80))
.fg(Color::Rgb(255, 235, 210))
}
pub fn forest() -> Self {
Self::default()
.brand(Color::Rgb(100, 200, 80))
.accent(Color::Rgb(80, 160, 80))
.dir(Color::Rgb(170, 220, 100))
.sel_bg(Color::Rgb(20, 50, 20))
.success(Color::Rgb(120, 210, 90))
.match_file(Color::Rgb(120, 210, 90))
.dim(Color::Rgb(90, 120, 80))
.fg(Color::Rgb(210, 235, 200))
}
pub fn rose() -> Self {
Self::default()
.brand(Color::Rgb(255, 100, 150))
.accent(Color::Rgb(255, 140, 180))
.dir(Color::Rgb(255, 180, 200))
.sel_bg(Color::Rgb(80, 20, 40))
.success(Color::Rgb(255, 160, 190))
.match_file(Color::Rgb(255, 160, 190))
.dim(Color::Rgb(140, 90, 110))
.fg(Color::Rgb(255, 230, 235))
}
pub fn mono() -> Self {
Self::default()
.brand(Color::Rgb(220, 220, 220))
.accent(Color::Rgb(180, 180, 180))
.dir(Color::Rgb(200, 200, 200))
.sel_bg(Color::Rgb(50, 50, 55))
.success(Color::Rgb(200, 200, 200))
.match_file(Color::Rgb(230, 230, 230))
.dim(Color::Rgb(110, 110, 115))
.fg(Color::Rgb(210, 210, 210))
}
pub fn neon() -> Self {
Self::default()
.brand(Color::Rgb(255, 0, 200))
.accent(Color::Rgb(0, 255, 200))
.dir(Color::Rgb(255, 220, 0))
.sel_bg(Color::Rgb(30, 0, 50))
.success(Color::Rgb(0, 255, 130))
.match_file(Color::Rgb(0, 255, 130))
.dim(Color::Rgb(100, 80, 120))
.fg(Color::Rgb(230, 230, 255))
}
pub fn all_presets() -> Vec<(&'static str, &'static str, Theme)> {
vec![
(
"Default",
"The built-in palette — orange title, cyan borders, yellow dirs",
Theme::default(),
),
(
"Grape",
"Deep violet & soft blue — easy on the eyes in dark environments",
Theme::grape(),
),
(
"Ocean",
"Teal & aquamarine — calm, nautical feel",
Theme::ocean(),
),
(
"Sunset",
"Warm amber & rose — vibrant, high-energy palette",
Theme::sunset(),
),
(
"Forest",
"Earthy greens & bark browns — natural, low-contrast",
Theme::forest(),
),
(
"Rose",
"Pinks & corals — playful, pastel-inspired",
Theme::rose(),
),
(
"Mono",
"Greyscale only — maximally distraction-free",
Theme::mono(),
),
(
"Neon",
"Electric brights on near-black — synthwave / retro",
Theme::neon(),
),
(
"Dracula",
"Pink, cyan & purple on dark grey",
Theme::dracula(),
),
("Nord", "Arctic bluish tones", Theme::nord()),
(
"Solarized Dark",
"Precision colours for machines and people — dark",
Theme::solarized_dark(),
),
(
"Solarized Light",
"Precision colours for machines and people — light",
Theme::solarized_light(),
),
(
"Gruvbox Dark",
"Retro groove — dark warm background",
Theme::gruvbox_dark(),
),
(
"Gruvbox Light",
"Retro groove — light warm background",
Theme::gruvbox_light(),
),
(
"Catppuccin Latte",
"Soothing pastel — light",
Theme::catppuccin_latte(),
),
(
"Catppuccin Frappé",
"Soothing pastel — medium-dark",
Theme::catppuccin_frappe(),
),
(
"Catppuccin Macchiato",
"Soothing pastel — dark",
Theme::catppuccin_macchiato(),
),
(
"Catppuccin Mocha",
"Soothing pastel — darkest",
Theme::catppuccin_mocha(),
),
(
"Tokyo Night",
"A clean dark blue / purple night",
Theme::tokyo_night(),
),
(
"Tokyo Night Storm",
"Tokyo Night on a slightly lighter background",
Theme::tokyo_night_storm(),
),
(
"Tokyo Night Light",
"Tokyo Night inverted to a light background",
Theme::tokyo_night_light(),
),
(
"Kanagawa Wave",
"Deep blue ink brushed on parchment",
Theme::kanagawa_wave(),
),
(
"Kanagawa Dragon",
"Darker earth tones — charcoal & moss",
Theme::kanagawa_dragon(),
),
(
"Kanagawa Lotus",
"Light parchment variant of Kanagawa",
Theme::kanagawa_lotus(),
),
(
"Moonfly",
"Deep dark background with vibrant accents",
Theme::moonfly(),
),
("Nightfly", "Deep ocean blues", Theme::nightfly()),
(
"Oxocarbon",
"IBM Carbon Design System inspired",
Theme::oxocarbon(),
),
]
}
}