- 1
//! 24-bit TrueColor theme definitions and minimalist typography contract - 2
//! for `vak term` (docs/design/55-rich-terminal-surface.md). - 3
- 4
use ratatui::style::{Color, Modifier, Style}; - 5
- 6
/// Minimalist symbols (no emojis, clean engineering glyphs). - 7
pub struct Symbols; - 8
- 9
impl Symbols { - 10
pub const CARET_EXPANDED: &'static str = "▾"; - 11
pub const CARET_COLLAPSED: &'static str = "▸"; - 12
pub const PROMPT_CHEVRON: &'static str = "❯"; - 13
pub const EXTERNAL_LINK: &'static str = "↗"; - 14
pub const STATUS_ACTIVE: &'static str = "●"; - 15
pub const STATUS_IDLE: &'static str = "○"; - 16
pub const CHECK: &'static str = "✓"; - 17
pub const CROSS: &'static str = "✗"; - 18
pub const DELTA: &'static str = "Δ"; - 19
pub const BULLET: &'static str = "•"; - 20
pub const WAVE: &'static str = "∿"; - 21
pub const SPINNER_FRAMES: &'static [&'static str] = - 22
&["⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏"]; - 23
} - 24
- 25
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)] - 26
pub enum ThemeKind { - 27
#[default] - 28
VakWarm, - 29
VakSlate, - 30
VakPaper, - 31
VakContrast, - 32
TokyoNight, - 33
} - 34
- 35
impl ThemeKind { - 36
pub fn label(&self) -> &'static str { - 37
match self { - 38
ThemeKind::VakWarm => "Vakyartha Warm (Terracotta)", - 39
ThemeKind::VakSlate => "Vakyartha Slate (Dark)", - 40
ThemeKind::VakPaper => "Vakyartha Paper (Light)", - 41
ThemeKind::VakContrast => "Vakyartha Contrast (OLED)", - 42
ThemeKind::TokyoNight => "Tokyo Night (Cyber)", - 43
} - 44
} - 45
- 46
pub fn next(&self) -> Self { - 47
match self { - 48
ThemeKind::VakWarm => ThemeKind::VakSlate, - 49
ThemeKind::VakSlate => ThemeKind::VakPaper, - 50
ThemeKind::VakPaper => ThemeKind::VakContrast, - 51
ThemeKind::VakContrast => ThemeKind::TokyoNight, - 52
ThemeKind::TokyoNight => ThemeKind::VakWarm, - 53
} - 54
} - 55
- 56
pub fn theme(&self) -> Theme { - 57
match self { - 58
ThemeKind::VakWarm => Theme::vak_warm(), - 59
ThemeKind::VakSlate => Theme::vak_slate(), - 60
ThemeKind::VakPaper => Theme::vak_paper(), - 61
ThemeKind::VakContrast => Theme::vak_contrast(), - 62
ThemeKind::TokyoNight => Theme::tokyo_night(), - 63
} - 64
} - 65
} - 66
- 67
#[derive(Debug, Clone)] - 68
pub struct Theme { - 69
pub kind: ThemeKind, - 70
pub bg: Color, - 71
pub surface: Color, - 72
pub surface_hover: Color, - 73
pub border: Color, - 74
pub border_focus: Color, - 75
pub accent: Color, - 76
pub accent_bright: Color, - 77
pub status_ok: Color, - 78
pub status_warn: Color, - 79
pub status_danger: Color, - 80
pub status_info: Color, - 81
pub text_main: Color, - 82
pub text_muted: Color, - 83
pub text_faint: Color, - 84
} - 85
- 86
impl Theme { - 87
/// Canonical Vakyartha Web Terracotta Theme (`#171714` / `#df795f`). - 88
pub fn vak_warm() -> Self { - 89
Self { - 90
kind: ThemeKind::VakWarm, - 91
bg: Color::Rgb(0x17, 0x17, 0x14), - 92
surface: Color::Rgb(0x1c, 0x1c, 0x19), - 93
surface_hover: Color::Rgb(0x29, 0x29, 0x25), - 94
border: Color::Rgb(0x34, 0x34, 0x2f), - 95
border_focus: Color::Rgb(0xdf, 0x79, 0x5f), - 96
accent: Color::Rgb(0xdf, 0x79, 0x5f), - 97
accent_bright: Color::Rgb(0xee, 0x92, 0x78), - 98
status_ok: Color::Rgb(0x73, 0xa9, 0x82), - 99
status_warn: Color::Rgb(0xd4, 0xa8, 0x5d), - 100
status_danger: Color::Rgb(0xd8, 0x6f, 0x72), - 101
status_info: Color::Rgb(0x7c, 0x9f, 0xc9), - 102
text_main: Color::Rgb(0xee, 0xea, 0xe2), - 103
text_muted: Color::Rgb(0x91, 0x8e, 0x86), - 104
text_faint: Color::Rgb(0x8b, 0x88, 0x80), - 105
} - 106
} - 107
- 108
/// Vakyartha Slate Theme (`#121419` / `#7f9fca`). - 109
pub fn vak_slate() -> Self { - 110
Self { - 111
kind: ThemeKind::VakSlate, - 112
bg: Color::Rgb(0x12, 0x14, 0x19), - 113
surface: Color::Rgb(0x17, 0x1a, 0x20), - 114
surface_hover: Color::Rgb(0x27, 0x2c, 0x34), - 115
border: Color::Rgb(0x33, 0x39, 0x43), - 116
border_focus: Color::Rgb(0x7f, 0x9f, 0xca), - 117
accent: Color::Rgb(0x7f, 0x9f, 0xca), - 118
accent_bright: Color::Rgb(0x9a, 0xb7, 0xdc), - 119
status_ok: Color::Rgb(0x73, 0xa9, 0x82), - 120
status_warn: Color::Rgb(0xd4, 0xa8, 0x5d), - 121
status_danger: Color::Rgb(0xd8, 0x6f, 0x72), - 122
status_info: Color::Rgb(0x9a, 0xb7, 0xdc), - 123
text_main: Color::Rgb(0xf1, 0xf5, 0xf9), - 124
text_muted: Color::Rgb(0x94, 0xa3, 0xb8), - 125
text_faint: Color::Rgb(0x64, 0x74, 0x8b), - 126
} - 127
} - 128
- 129
/// Vakyartha Paper Light Theme (`#f4f1ea` / `#a8462a`). - 130
pub fn vak_paper() -> Self { - 131
Self { - 132
kind: ThemeKind::VakPaper, - 133
bg: Color::Rgb(0xf4, 0xf1, 0xea), - 134
surface: Color::Rgb(0xfa, 0xf8, 0xf3), - 135
surface_hover: Color::Rgb(0xef, 0xeb, 0xe1), - 136
border: Color::Rgb(0xd9, 0xd3, 0xc6), - 137
border_focus: Color::Rgb(0xa8, 0x46, 0x2a), - 138
accent: Color::Rgb(0xa8, 0x46, 0x2a), - 139
accent_bright: Color::Rgb(0x8d, 0x39, 0x21), - 140
status_ok: Color::Rgb(0x2f, 0x6b, 0x40), - 141
status_warn: Color::Rgb(0x7a, 0x54, 0x11), - 142
status_danger: Color::Rgb(0xa5, 0x2a, 0x2f), - 143
status_info: Color::Rgb(0x2f, 0x55, 0x80), - 144
text_main: Color::Rgb(0x23, 0x21, 0x1c), - 145
text_muted: Color::Rgb(0x63, 0x5f, 0x54), - 146
text_faint: Color::Rgb(0x6c, 0x67, 0x5b), - 147
} - 148
} - 149
- 150
/// Vakyartha Contrast OLED Theme (`#080808` / `#ff8e70`). - 151
pub fn vak_contrast() -> Self { - 152
Self { - 153
kind: ThemeKind::VakContrast, - 154
bg: Color::Rgb(0x08, 0x08, 0x08), - 155
surface: Color::Rgb(0x10, 0x10, 0x10), - 156
surface_hover: Color::Rgb(0x24, 0x24, 0x24), - 157
border: Color::Rgb(0x52, 0x52, 0x52), - 158
border_focus: Color::Rgb(0xff, 0x8e, 0x70), - 159
accent: Color::Rgb(0xff, 0x8e, 0x70), - 160
accent_bright: Color::Rgb(0xff, 0xa4, 0x8d), - 161
status_ok: Color::Rgb(0x00, 0xe6, 0x76), - 162
status_warn: Color::Rgb(0xff, 0xd6, 0x00), - 163
status_danger: Color::Rgb(0xff, 0x52, 0x52), - 164
status_info: Color::Rgb(0x40, 0xc4, 0xff), - 165
text_main: Color::Rgb(0xff, 0xff, 0xff), - 166
text_muted: Color::Rgb(0xb9, 0xb9, 0xb9), - 167
text_faint: Color::Rgb(0x85, 0x85, 0x85), - 168
} - 169
} - 170
- 171
/// Tokyo Night Cyber Theme (`#1a1b26` / `#70d6ff`). - 172
pub fn tokyo_night() -> Self { - 173
Self { - 174
kind: ThemeKind::TokyoNight, - 175
bg: Color::Rgb(0x1a, 0x1b, 0x26), - 176
surface: Color::Rgb(0x24, 0x28, 0x3b), - 177
surface_hover: Color::Rgb(0x2f, 0x35, 0x4e), - 178
border: Color::Rgb(0x41, 0x48, 0x68), - 179
border_focus: Color::Rgb(0x70, 0xd6, 0xff), - 180
accent: Color::Rgb(0x70, 0xd6, 0xff), - 181
accent_bright: Color::Rgb(0xb4, 0xf9, 0xf8), - 182
status_ok: Color::Rgb(0x9e, 0xce, 0x6a), - 183
status_warn: Color::Rgb(0xe0, 0xaf, 0x68), - 184
status_danger: Color::Rgb(0xf7, 0x76, 0x8e), - 185
status_info: Color::Rgb(0x7a, 0xa2, 0xf7), - 186
text_main: Color::Rgb(0xc0, 0xca, 0xf5), - 187
text_muted: Color::Rgb(0x9a, 0xa5, 0xce), - 188
text_faint: Color::Rgb(0x56, 0x5f, 0x89), - 189
} - 190
} - 191
- 192
// Helper styles - 193
pub fn style_base(&self) -> Style { - 194
Style::default().bg(self.bg).fg(self.text_main) - 195
} - 196
- 197
pub fn style_card(&self) -> Style { - 198
Style::default().bg(self.surface).fg(self.text_main) - 199
} - 200
- 201
pub fn style_border(&self) -> Style { - 202
Style::default().fg(self.border) - 203
} - 204
- 205
pub fn style_border_focus(&self) -> Style { - 206
Style::default().fg(self.border_focus) - 207
} - 208
- 209
pub fn style_accent(&self) -> Style { - 210
Style::default().fg(self.accent) - 211
} - 212
- 213
pub fn style_tab_active(&self) -> Style { - 214
Style::default() - 215
.bg(self.accent) - 216
.fg(self.bg) - 217
.add_modifier(Modifier::BOLD) - 218
} - 219
- 220
pub fn style_tab_inactive(&self) -> Style { - 221
Style::default().bg(self.surface).fg(self.text_muted) - 222
} - 223
- 224
pub fn style_ok(&self) -> Style { - 225
Style::default().fg(self.status_ok) - 226
} - 227
- 228
pub fn style_warn(&self) -> Style { - 229
Style::default().fg(self.status_warn) - 230
} - 231
- 232
pub fn style_danger(&self) -> Style { - 233
Style::default().fg(self.status_danger) - 234
} - 235
- 236
pub fn style_info(&self) -> Style { - 237
Style::default().fg(self.status_info) - 238
} - 239
- 240
pub fn style_diff_add(&self) -> Style { - 241
Style::default() - 242
.bg(Color::Rgb(0x1a, 0x2e, 0x22)) - 243
.fg(self.status_ok) - 244
} - 245
- 246
pub fn style_diff_del(&self) -> Style { - 247
Style::default() - 248
.bg(Color::Rgb(0x35, 0x19, 0x1b)) - 249
.fg(self.status_danger) - 250
} - 251
} - 252
Indexing the workspace…
Vakyartha documentation is discovering safe artifacts, anchors, and source references.