1use crate::{Label, LabelCommon, component_prelude::*, v_flex};
2use documented::{DocumentedFields, DocumentedVariants};
3use gpui::{App, Hsla, IntoElement, ParentElement, Styled};
4use theme::ActiveTheme;
5
6/// Sets a color that has a consistent meaning across all themes.
7#[derive(
8 Debug,
9 Default,
10 Eq,
11 PartialEq,
12 Copy,
13 Clone,
14 RegisterComponent,
15 Documented,
16 DocumentedFields,
17 DocumentedVariants,
18)]
19pub enum Color {
20 #[default]
21 /// The default text color. Might be known as "foreground" or "primary" in
22 /// some theme systems.
23 ///
24 /// For less emphasis, consider using [`Color::Muted`] or [`Color::Hidden`].
25 Default,
26 /// A text color used for accents, such as links or highlights.
27 Accent,
28 /// A color used to indicate a conflict, such as a version control merge conflict, or a conflict between a file in the editor and the file system.
29 Conflict,
30 /// A color used to indicate a newly created item, such as a new file in
31 /// version control, or a new file on disk.
32 Created,
33 /// It is highly, HIGHLY recommended not to use this! Using this color
34 /// means detaching it from any semantic meaning across themes.
35 ///
36 /// A custom color specified by an HSLA value.
37 Custom(Hsla),
38 /// A color used for all debugger UI elements.
39 Debugger,
40 /// A color used to indicate a deleted item, such as a file removed from version control.
41 Deleted,
42 /// A color used for disabled UI elements or text, like a disabled button or menu item.
43 Disabled,
44 /// A color used to indicate an error condition, or something the user
45 /// cannot do. In very rare cases, it might be used to indicate dangerous or
46 /// destructive action.
47 Error,
48 /// A color used for elements that represent something that is hidden, like
49 /// a hidden file, or an element that should be visually de-emphasized.
50 Hidden,
51 /// A color used for hint or suggestion text, often a blue color. Use this
52 /// color to represent helpful, or semantically neutral information.
53 Hint,
54 /// A color used for items that are intentionally ignored, such as files ignored by version control.
55 Ignored,
56 /// A color used for informational messages or status indicators, often a blue color.
57 Info,
58 /// A color used to indicate a modified item, such as an edited file, or a modified entry in version control.
59 Modified,
60 /// A color used for text or UI elements that should be visually muted or de-emphasized.
61 ///
62 /// For more emphasis, consider using [`Color::Default`].
63 ///
64 /// For less emphasis, consider using [`Color::Hidden`].
65 Muted,
66 /// A color used for placeholder text in input fields.
67 Placeholder,
68 /// A color associated with a specific player number.
69 Player(u32),
70 /// A color used to indicate selected text or UI elements.
71 Selected,
72 /// A color used to indicate a successful operation or status.
73 Success,
74 /// A version control color used to indicate a newly added file or content in version control.
75 VersionControlAdded,
76 /// A version control color used to indicate conflicting changes that need resolution.
77 VersionControlConflict,
78 /// A version control color used to indicate a file or content that has been deleted in version control.
79 VersionControlDeleted,
80 /// A version control color used to indicate files or content that is being ignored by version control.
81 VersionControlIgnored,
82 /// A version control color used to indicate modified files or content in version control.
83 VersionControlModified,
84 /// A color used to indicate a warning condition.
85 Warning,
86}
87
88impl Color {
89 /// Returns the Color's HSLA value.
90 pub fn color(&self, cx: &App) -> Hsla {
91 match self {
92 Color::Default => cx.theme().colors().text,
93 Color::Muted => cx.theme().colors().text_muted,
94 Color::Created => cx.theme().status().created,
95 Color::Modified => cx.theme().status().modified,
96 Color::Conflict => cx.theme().status().conflict,
97 Color::Ignored => cx.theme().status().ignored,
98 Color::Debugger => cx.theme().colors().debugger_accent,
99 Color::Deleted => cx.theme().status().deleted,
100 Color::Disabled => cx.theme().colors().text_disabled,
101 Color::Hidden => cx.theme().status().hidden,
102 Color::Hint => cx.theme().status().hint,
103 Color::Info => cx.theme().status().info,
104 Color::Placeholder => cx.theme().colors().text_placeholder,
105 Color::Accent => cx.theme().colors().text_accent,
106 Color::Player(i) => cx.theme().styles.player.color_for_participant(*i).cursor,
107 Color::Error => cx.theme().status().error,
108 Color::Selected => cx.theme().colors().text_accent,
109 Color::Success => cx.theme().status().success,
110 Color::VersionControlAdded => cx.theme().colors().version_control_added,
111 Color::VersionControlConflict => cx.theme().colors().version_control_conflict,
112 Color::VersionControlDeleted => cx.theme().colors().version_control_deleted,
113 Color::VersionControlIgnored => cx.theme().colors().version_control_ignored,
114 Color::VersionControlModified => cx.theme().colors().version_control_modified,
115 Color::Warning => cx.theme().status().warning,
116 Color::Custom(color) => *color,
117 }
118 }
119}
120
121impl From<Hsla> for Color {
122 fn from(color: Hsla) -> Self {
123 Color::Custom(color)
124 }
125}
126
127impl Component for Color {
128 fn scope() -> ComponentScope {
129 ComponentScope::Utilities
130 }
131
132 fn description() -> Option<&'static str> {
133 Some(Color::DOCS)
134 }
135
136 fn preview(_window: &mut gpui::Window, _cx: &mut App) -> Option<gpui::AnyElement> {
137 Some(
138 v_flex()
139 .gap_6()
140 .children(vec![
141 example_group_with_title(
142 "Text Colors",
143 vec![
144 single_example(
145 "Default",
146 Label::new("Default text color")
147 .color(Color::Default)
148 .into_any_element(),
149 )
150 .description(Color::Default.get_variant_docs()),
151 single_example(
152 "Muted",
153 Label::new("Muted text color")
154 .color(Color::Muted)
155 .into_any_element(),
156 )
157 .description(Color::Muted.get_variant_docs()),
158 single_example(
159 "Accent",
160 Label::new("Accent text color")
161 .color(Color::Accent)
162 .into_any_element(),
163 )
164 .description(Color::Accent.get_variant_docs()),
165 single_example(
166 "Disabled",
167 Label::new("Disabled text color")
168 .color(Color::Disabled)
169 .into_any_element(),
170 )
171 .description(Color::Disabled.get_variant_docs()),
172 ],
173 ),
174 example_group_with_title(
175 "Status Colors",
176 vec![
177 single_example(
178 "Success",
179 Label::new("Success status")
180 .color(Color::Success)
181 .into_any_element(),
182 )
183 .description(Color::Success.get_variant_docs()),
184 single_example(
185 "Warning",
186 Label::new("Warning status")
187 .color(Color::Warning)
188 .into_any_element(),
189 )
190 .description(Color::Warning.get_variant_docs()),
191 single_example(
192 "Error",
193 Label::new("Error status")
194 .color(Color::Error)
195 .into_any_element(),
196 )
197 .description(Color::Error.get_variant_docs()),
198 single_example(
199 "Info",
200 Label::new("Info status")
201 .color(Color::Info)
202 .into_any_element(),
203 )
204 .description(Color::Info.get_variant_docs()),
205 ],
206 ),
207 example_group_with_title(
208 "Version Control Colors",
209 vec![
210 single_example(
211 "Created",
212 Label::new("Created item")
213 .color(Color::Created)
214 .into_any_element(),
215 )
216 .description(Color::Created.get_variant_docs()),
217 single_example(
218 "Modified",
219 Label::new("Modified item")
220 .color(Color::Modified)
221 .into_any_element(),
222 )
223 .description(Color::Modified.get_variant_docs()),
224 single_example(
225 "Deleted",
226 Label::new("Deleted item")
227 .color(Color::Deleted)
228 .into_any_element(),
229 )
230 .description(Color::Deleted.get_variant_docs()),
231 single_example(
232 "Conflict",
233 Label::new("Conflict item")
234 .color(Color::Conflict)
235 .into_any_element(),
236 )
237 .description(Color::Conflict.get_variant_docs()),
238 ],
239 ),
240 ])
241 .into_any_element(),
242 )
243 }
244}