1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
//! Everforest Dark Medium color palette and pre-composed [`ratatui`] style helpers.
//!
//! [`EverforestTheme`] is a unit struct used as a namespace for `const Color` values
//! and functions that return pre-composed [`ratatui::style::Style`] objects.
//! Import it with `use crate::theme::EverforestTheme as T;` to keep call sites short.
use ratatui::style::{Color, Modifier, Style};
/// Everforest Dark Medium color palette and style helpers
pub struct EverforestTheme;
#[allow(dead_code)]
impl EverforestTheme {
// ── Backgrounds ──────────────────────────────────────────────────────────
pub const BG_DIM: Color = Color::Rgb(0x23, 0x2A, 0x2E); // #232A2E
pub const BG0: Color = Color::Rgb(0x2D, 0x35, 0x3B); // #2D353B — main bg
pub const BG1: Color = Color::Rgb(0x34, 0x3F, 0x44); // #343F44 — cursor line
pub const BG2: Color = Color::Rgb(0x3D, 0x48, 0x4D); // #3D484D — selection
pub const BG3: Color = Color::Rgb(0x47, 0x52, 0x58); // #475258 — header/status
pub const BG4: Color = Color::Rgb(0x4F, 0x58, 0x5E); // #4F585E — separators
// ── Foregrounds ──────────────────────────────────────────────────────────
pub const FG: Color = Color::Rgb(0xD3, 0xC6, 0xAA); // #D3C6AA — main text
pub const RED: Color = Color::Rgb(0xE6, 0x7E, 0x80); // #E67E80
pub const ORANGE: Color = Color::Rgb(0xE6, 0x98, 0x75); // #E69875
pub const YELLOW: Color = Color::Rgb(0xDB, 0xBC, 0x7F); // #DBBC7F
pub const GREEN: Color = Color::Rgb(0xA7, 0xC0, 0x80); // #A7C080
pub const AQUA: Color = Color::Rgb(0x83, 0xC0, 0x92); // #83C092
pub const BLUE: Color = Color::Rgb(0x7F, 0xBB, 0xB3); // #7FBBB3
pub const PURPLE: Color = Color::Rgb(0xD6, 0x99, 0xB6); // #D699B6
pub const GREY0: Color = Color::Rgb(0x7A, 0x84, 0x78); // #7A8478
pub const GREY1: Color = Color::Rgb(0x85, 0x92, 0x89); // #859289
pub const GREY2: Color = Color::Rgb(0x9D, 0xA9, 0xA0); // #9DA9A0
// ── Style helpers ─────────────────────────────────────────────────────────
/// Bold green text on [`Self::BG3`] (header/status background) for table column headers.
pub fn header_style() -> Style {
Style::default()
.fg(Self::GREEN)
.bg(Self::BG3)
.add_modifier(Modifier::BOLD)
}
/// Alternating row background: [`Self::BG0`] for even-indexed rows, [`Self::BG_DIM`] for odd.
pub fn normal_row_style(index: usize) -> Style {
let bg = if index.is_multiple_of(2) {
Self::BG0
} else {
Self::BG_DIM
};
Style::default().fg(Self::FG).bg(bg)
}
/// Cursor (active) row — full inversion: bright fg becomes bg, dark bg becomes fg.
/// The active column cell gets an extra BOLD marker; other cells are bold too.
pub fn active_row_style() -> Style {
Style::default()
.fg(Self::BG_DIM) // dark text on bright
.bg(Self::FG) // #D3C6AA — cream/wheat background
.add_modifier(Modifier::BOLD)
}
/// The single cell at the intersection of cursor row AND cursor column.
/// Slightly deeper colour so the column is still distinguishable.
pub fn active_row_col_style() -> Style {
Style::default()
.fg(Self::BG_DIM)
.bg(Self::AQUA) // teal, same as the header indicator
.add_modifier(Modifier::BOLD)
}
/// Header cell of the currently active column.
pub fn selected_col_header_style() -> Style {
Style::default()
.fg(Self::BG_DIM)
.bg(Self::AQUA)
.add_modifier(Modifier::BOLD)
}
/// Row selected by the user ('s' key) — yellow accent text, normal background.
/// **No** background fill — the row blends with alternating rows but text pops.
pub fn selected_mark_style(index: usize) -> Style {
let bg = if index.is_multiple_of(2) {
Self::BG0
} else {
Self::BG_DIM
};
Style::default()
.fg(Self::YELLOW)
.bg(bg)
.add_modifier(Modifier::BOLD)
}
/// Selected row AND it is the active (cursor) row — invert, but tint with YELLOW.
pub fn selected_active_row_style() -> Style {
Style::default()
.fg(Self::BG_DIM)
.bg(Self::YELLOW) // yellow bg, dark text
.add_modifier(Modifier::BOLD)
}
/// Active-column cell on a selected+active row.
pub fn selected_active_col_style() -> Style {
Style::default()
.fg(Self::BG_DIM)
.bg(Self::ORANGE)
.add_modifier(Modifier::BOLD)
}
/// Kept for aggregators footer compatibility.
pub fn selected_row_style() -> Style {
Style::default()
.fg(Self::AQUA)
.bg(Self::BG2)
.add_modifier(Modifier::BOLD)
}
pub fn status_bar_style() -> Style {
Style::default().fg(Self::FG).bg(Self::BG3)
}
pub fn mode_indicator_style() -> Style {
Style::default()
.fg(Self::BG0)
.bg(Self::GREEN)
.add_modifier(Modifier::BOLD)
}
pub fn filter_input_style() -> Style {
Style::default().fg(Self::YELLOW).bg(Self::BG1)
}
pub fn error_style() -> Style {
Style::default().fg(Self::RED)
}
pub fn sort_asc_style() -> Style {
Style::default().fg(Self::BLUE)
}
pub fn sort_desc_style() -> Style {
Style::default().fg(Self::ORANGE)
}
pub fn frequency_bar_style() -> Style {
Style::default().fg(Self::GREEN).bg(Self::BG_DIM)
}
pub fn scrollbar_style() -> Style {
Style::default().fg(Self::GREY1)
}
pub fn separator_style() -> Style {
Style::default().fg(Self::GREY0)
}
pub fn footer_style() -> Style {
Style::default()
.fg(Self::PURPLE)
.bg(Self::BG3)
.add_modifier(Modifier::ITALIC)
}
}