1use ratatui::style::Color;
2use serde::{Deserialize, Serialize};
3
4#[derive(Debug, Clone, Serialize, Deserialize)]
6pub struct Theme {
7 pub name: String,
8 pub colors: ThemeColors,
9}
10
11#[derive(Debug, Clone, Serialize, Deserialize)]
12pub struct ThemeColors {
13 pub background: ColorValue,
15 pub foreground: ColorValue,
16
17 pub border: ColorValue,
19 pub border_focused: ColorValue,
20 pub header: ColorValue,
21 pub status_bar: ColorValue,
22
23 pub text_primary: ColorValue,
25 pub text_secondary: ColorValue,
26 pub text_disabled: ColorValue,
27 pub text_highlight: ColorValue,
28
29 pub user_message: ColorValue,
31 pub assistant_message: ColorValue,
32 pub system_message: ColorValue,
33
34 pub code_background: ColorValue,
36 pub code_foreground: ColorValue,
37 pub code_keyword: ColorValue,
38 pub code_string: ColorValue,
39 pub code_comment: ColorValue,
40
41 pub mode_normal: ColorValue,
43 pub mode_accept_edits: ColorValue,
44 pub mode_plan: ColorValue,
45 pub mode_bypass_all: ColorValue,
46
47 pub success: ColorValue,
49 pub warning: ColorValue,
50 pub error: ColorValue,
51 pub info: ColorValue,
52}
53
54#[derive(Debug, Clone, Serialize, Deserialize)]
55#[serde(untagged)]
56pub enum ColorValue {
57 Rgb { r: u8, g: u8, b: u8 },
58 Named(String),
59}
60
61impl ColorValue {
62 pub fn to_color(&self) -> Color {
63 match self {
64 ColorValue::Rgb { r, g, b } => Color::Rgb(*r, *g, *b),
65 ColorValue::Named(name) => match name.as_str() {
66 "black" => Color::Black,
67 "red" => Color::Red,
68 "green" => Color::Green,
69 "yellow" => Color::Yellow,
70 "blue" => Color::Blue,
71 "magenta" => Color::Magenta,
72 "cyan" => Color::Cyan,
73 "white" => Color::White,
74 "gray" | "grey" => Color::Gray,
75 "dark_gray" | "dark_grey" => Color::DarkGray,
76 _ => Color::White,
77 },
78 }
79 }
80}
81
82impl Theme {
83 pub fn light() -> Self {
90 Self {
91 name: "Light".to_string(),
92 colors: ThemeColors {
93 background: ColorValue::Rgb {
94 r: 250,
95 g: 250,
96 b: 250,
97 },
98 foreground: ColorValue::Rgb {
99 r: 30,
100 g: 30,
101 b: 30,
102 },
103
104 border: ColorValue::Named("gray".to_string()),
105 border_focused: ColorValue::Named("blue".to_string()),
106 header: ColorValue::Named("blue".to_string()),
107 status_bar: ColorValue::Named("white".to_string()),
108
109 text_primary: ColorValue::Named("black".to_string()),
110 text_secondary: ColorValue::Named("dark_gray".to_string()),
111 text_disabled: ColorValue::Named("gray".to_string()),
112 text_highlight: ColorValue::Named("magenta".to_string()),
113
114 user_message: ColorValue::Named("blue".to_string()),
115 assistant_message: ColorValue::Named("green".to_string()),
116 system_message: ColorValue::Named("yellow".to_string()),
117
118 code_background: ColorValue::Rgb {
119 r: 240,
120 g: 240,
121 b: 240,
122 },
123 code_foreground: ColorValue::Named("dark_gray".to_string()),
124 code_keyword: ColorValue::Named("magenta".to_string()),
125 code_string: ColorValue::Named("green".to_string()),
126 code_comment: ColorValue::Named("gray".to_string()),
127
128 mode_normal: ColorValue::Named("green".to_string()),
129 mode_accept_edits: ColorValue::Named("yellow".to_string()),
130 mode_plan: ColorValue::Named("blue".to_string()),
131 mode_bypass_all: ColorValue::Named("red".to_string()),
132
133 success: ColorValue::Named("green".to_string()),
134 warning: ColorValue::Named("yellow".to_string()),
135 error: ColorValue::Named("red".to_string()),
136 info: ColorValue::Named("blue".to_string()),
137 },
138 }
139 }
140
141 pub fn dark() -> Self {
143 Self {
144 name: "Dark".to_string(),
145 colors: ThemeColors {
146 background: ColorValue::Rgb {
147 r: 20,
148 g: 20,
149 b: 20,
150 },
151 foreground: ColorValue::Rgb {
152 r: 230,
153 g: 230,
154 b: 230,
155 },
156
157 border: ColorValue::Named("dark_gray".to_string()),
158 border_focused: ColorValue::Named("cyan".to_string()),
159 header: ColorValue::Named("cyan".to_string()),
160 status_bar: ColorValue::Named("black".to_string()),
161
162 text_primary: ColorValue::Named("white".to_string()),
163 text_secondary: ColorValue::Named("gray".to_string()),
164 text_disabled: ColorValue::Named("dark_gray".to_string()),
165 text_highlight: ColorValue::Named("yellow".to_string()),
166
167 user_message: ColorValue::Named("blue".to_string()),
168 assistant_message: ColorValue::Named("green".to_string()),
169 system_message: ColorValue::Named("yellow".to_string()),
170
171 code_background: ColorValue::Rgb {
172 r: 40,
173 g: 40,
174 b: 40,
175 },
176 code_foreground: ColorValue::Named("gray".to_string()),
177 code_keyword: ColorValue::Named("magenta".to_string()),
178 code_string: ColorValue::Named("green".to_string()),
179 code_comment: ColorValue::Named("dark_gray".to_string()),
180
181 mode_normal: ColorValue::Named("green".to_string()),
182 mode_accept_edits: ColorValue::Named("yellow".to_string()),
183 mode_plan: ColorValue::Named("blue".to_string()),
184 mode_bypass_all: ColorValue::Named("red".to_string()),
185
186 success: ColorValue::Named("green".to_string()),
187 warning: ColorValue::Named("yellow".to_string()),
188 error: ColorValue::Named("red".to_string()),
189 info: ColorValue::Named("cyan".to_string()),
190 },
191 }
192 }
193}