1// NOTE – This should be removed
2// I (Nate) need to come back and check if we are still using this anywhere
3
4import chroma, { Color, Scale } from "chroma-js";
5import { fontWeights } from "../../common";
6import { withOpacity } from "../../utils/color";
7import Theme, { buildPlayer, Syntax } from "./theme";
8
9export function colorRamp(color: Color): Scale {
10 let hue = color.hsl()[0];
11 let endColor = chroma.hsl(hue, 0.88, 0.96);
12 let startColor = chroma.hsl(hue, 0.68, 0.12);
13 return chroma.scale([startColor, color, endColor]).mode("hsl");
14}
15
16export function createTheme(
17 name: string,
18 isLight: boolean,
19 color_ramps: { [rampName: string]: Scale }
20): Theme {
21 let ramps: typeof color_ramps = {};
22 // Chromajs mutates the underlying ramp when you call domain. This causes problems because
23 // we now store the ramps object in the theme so that we can pull colors out of them.
24 // So instead of calling domain and storing the result, we have to construct new ramps for each
25 // theme so that we don't modify the passed in ramps.
26 // This combined with an error in the type definitions for chroma js means we have to cast the colors
27 // function to any in order to get the colors back out from the original ramps.
28 if (isLight) {
29 for (var rampName in color_ramps) {
30 ramps[rampName] = chroma
31 .scale((color_ramps[rampName].colors as any)())
32 .domain([1, 0]);
33 }
34 ramps.neutral = chroma
35 .scale((color_ramps.neutral.colors as any)())
36 .domain([7, 0]);
37 } else {
38 for (var rampName in color_ramps) {
39 ramps[rampName] = chroma
40 .scale((color_ramps[rampName].colors as any)())
41 .domain([0, 1]);
42 }
43 ramps.neutral = chroma
44 .scale((color_ramps.neutral.colors as any)())
45 .domain([0, 7]);
46 }
47
48 let blend = isLight ? 0.12 : 0.24;
49
50 function sample(ramp: Scale, index: number): string {
51 return ramp(index).hex();
52 }
53 const darkest = ramps.neutral(isLight ? 7 : 0).hex();
54
55 const backgroundColor = {
56 // Title bar
57 100: {
58 base: sample(ramps.neutral, 1.25),
59 hovered: sample(ramps.neutral, 1.5),
60 active: sample(ramps.neutral, 1.75),
61 },
62 // Midground (panels, etc)
63 300: {
64 base: sample(ramps.neutral, 1),
65 hovered: sample(ramps.neutral, 1.25),
66 active: sample(ramps.neutral, 1.5),
67 },
68 // Editor
69 500: {
70 base: sample(ramps.neutral, 0),
71 hovered: sample(ramps.neutral, 0.25),
72 active: sample(ramps.neutral, 0.5),
73 },
74 on300: {
75 base: sample(ramps.neutral, 0),
76 hovered: sample(ramps.neutral, 0.5),
77 active: sample(ramps.neutral, 1),
78 },
79 on500: {
80 base: sample(ramps.neutral, 1),
81 hovered: sample(ramps.neutral, 1.5),
82 active: sample(ramps.neutral, 2),
83 },
84 ok: {
85 base: withOpacity(sample(ramps.green, 0.5), 0.15),
86 hovered: withOpacity(sample(ramps.green, 0.5), 0.2),
87 active: withOpacity(sample(ramps.green, 0.5), 0.25),
88 },
89 error: {
90 base: withOpacity(sample(ramps.red, 0.5), 0.15),
91 hovered: withOpacity(sample(ramps.red, 0.5), 0.2),
92 active: withOpacity(sample(ramps.red, 0.5), 0.25),
93 },
94 on500Error: {
95 base: sample(ramps.red, 0.05),
96 hovered: sample(ramps.red, 0.1),
97 active: sample(ramps.red, 0.15),
98 },
99 warning: {
100 base: withOpacity(sample(ramps.yellow, 0.5), 0.15),
101 hovered: withOpacity(sample(ramps.yellow, 0.5), 0.2),
102 active: withOpacity(sample(ramps.yellow, 0.5), 0.25),
103 },
104 on500Warning: {
105 base: sample(ramps.yellow, 0.05),
106 hovered: sample(ramps.yellow, 0.1),
107 active: sample(ramps.yellow, 0.15),
108 },
109 info: {
110 base: withOpacity(sample(ramps.blue, 0.5), 0.15),
111 hovered: withOpacity(sample(ramps.blue, 0.5), 0.2),
112 active: withOpacity(sample(ramps.blue, 0.5), 0.25),
113 },
114 on500Info: {
115 base: sample(ramps.blue, 0.05),
116 hovered: sample(ramps.blue, 0.1),
117 active: sample(ramps.blue, 0.15),
118 },
119 on500Ok: {
120 base: sample(ramps.green, 0.05),
121 hovered: sample(ramps.green, 0.1),
122 active: sample(ramps.green, 0.15),
123 },
124 };
125
126 const borderColor = {
127 primary: sample(ramps.neutral, isLight ? 1.5 : 0),
128 secondary: sample(ramps.neutral, isLight ? 1.25 : 1),
129 muted: sample(ramps.neutral, isLight ? 1.25 : 3),
130 active: sample(ramps.neutral, isLight ? 4 : 3),
131 onMedia: withOpacity(darkest, 0.1),
132 ok: sample(ramps.green, 0.3),
133 error: sample(ramps.red, 0.3),
134 warning: sample(ramps.yellow, 0.3),
135 info: sample(ramps.blue, 0.3),
136 };
137
138 const textColor = {
139 primary: sample(ramps.neutral, 6),
140 secondary: sample(ramps.neutral, 5),
141 muted: sample(ramps.neutral, 4),
142 placeholder: sample(ramps.neutral, 3),
143 active: sample(ramps.neutral, 7),
144 feature: sample(ramps.blue, 0.5),
145 ok: sample(ramps.green, 0.5),
146 error: sample(ramps.red, 0.5),
147 warning: sample(ramps.yellow, 0.5),
148 info: sample(ramps.blue, 0.5),
149 onMedia: darkest,
150 };
151
152 const player = {
153 1: buildPlayer(sample(ramps.blue, 0.5)),
154 2: buildPlayer(sample(ramps.green, 0.5)),
155 3: buildPlayer(sample(ramps.magenta, 0.5)),
156 4: buildPlayer(sample(ramps.orange, 0.5)),
157 5: buildPlayer(sample(ramps.violet, 0.5)),
158 6: buildPlayer(sample(ramps.cyan, 0.5)),
159 7: buildPlayer(sample(ramps.red, 0.5)),
160 8: buildPlayer(sample(ramps.yellow, 0.5)),
161 };
162
163 const editor = {
164 background: backgroundColor[500].base,
165 indent_guide: borderColor.muted,
166 indent_guide_active: borderColor.secondary,
167 line: {
168 active: sample(ramps.neutral, 1),
169 highlighted: sample(ramps.neutral, 1.25), // TODO: Where is this used?
170 },
171 highlight: {
172 selection: player[1].selectionColor,
173 occurrence: withOpacity(sample(ramps.neutral, 3.5), blend),
174 activeOccurrence: withOpacity(sample(ramps.neutral, 3.5), blend * 2), // TODO: Not hooked up - https://github.com/zed-industries/zed/issues/751
175 matchingBracket: backgroundColor[500].active, // TODO: Not hooked up
176 match: sample(ramps.violet, 0.15),
177 activeMatch: withOpacity(sample(ramps.violet, 0.4), blend * 2), // TODO: Not hooked up - https://github.com/zed-industries/zed/issues/751
178 related: backgroundColor[500].hovered,
179 },
180 gutter: {
181 primary: textColor.placeholder,
182 active: textColor.active,
183 },
184 };
185
186 const syntax: Syntax = {
187 primary: {
188 color: sample(ramps.neutral, 7),
189 weight: fontWeights.normal,
190 },
191 "variable.special": {
192 color: sample(ramps.blue, 0.8),
193 weight: fontWeights.normal,
194 },
195 comment: {
196 color: sample(ramps.neutral, 5),
197 weight: fontWeights.normal,
198 },
199 punctuation: {
200 color: sample(ramps.neutral, 6),
201 weight: fontWeights.normal,
202 },
203 constant: {
204 color: sample(ramps.neutral, 4),
205 weight: fontWeights.normal,
206 },
207 keyword: {
208 color: sample(ramps.blue, 0.5),
209 weight: fontWeights.normal,
210 },
211 function: {
212 color: sample(ramps.yellow, 0.5),
213 weight: fontWeights.normal,
214 },
215 type: {
216 color: sample(ramps.cyan, 0.5),
217 weight: fontWeights.normal,
218 },
219 constructor: {
220 color: sample(ramps.cyan, 0.5),
221 weight: fontWeights.normal,
222 },
223 property: {
224 color: sample(ramps.blue, 0.6),
225 weight: fontWeights.normal,
226 },
227 enum: {
228 color: sample(ramps.orange, 0.5),
229 weight: fontWeights.normal,
230 },
231 operator: {
232 color: sample(ramps.orange, 0.5),
233 weight: fontWeights.normal,
234 },
235 string: {
236 color: sample(ramps.orange, 0.5),
237 weight: fontWeights.normal,
238 },
239 number: {
240 color: sample(ramps.green, 0.5),
241 weight: fontWeights.normal,
242 },
243 boolean: {
244 color: sample(ramps.green, 0.5),
245 weight: fontWeights.normal,
246 },
247 predictive: {
248 color: textColor.muted,
249 weight: fontWeights.normal,
250 },
251 title: {
252 color: sample(ramps.yellow, 0.5),
253 weight: fontWeights.bold,
254 },
255 emphasis: {
256 color: textColor.feature,
257 weight: fontWeights.normal,
258 },
259 "emphasis.strong": {
260 color: textColor.feature,
261 weight: fontWeights.bold,
262 },
263 linkUri: {
264 color: sample(ramps.green, 0.5),
265 weight: fontWeights.normal,
266 underline: true,
267 },
268 linkText: {
269 color: sample(ramps.orange, 0.5),
270 weight: fontWeights.normal,
271 italic: true,
272 },
273 };
274
275 const shadow = withOpacity(
276 ramps
277 .neutral(isLight ? 7 : 0)
278 .darken()
279 .hex(),
280 blend
281 );
282
283 return {
284 name,
285 isLight,
286 backgroundColor,
287 borderColor,
288 textColor,
289 iconColor: textColor,
290 editor,
291 syntax,
292 player,
293 shadow,
294 ramps,
295 };
296}