1import { ColorScheme } from "../theme/colorScheme"
2import { withOpacity } from "../theme/color"
3import { toggleable } from "./toggle"
4import {
5 background,
6 border,
7 borderColor,
8 foreground,
9 svg,
10 text,
11} from "./components"
12import statusBar from "./statusBar"
13import tabBar from "./tabBar"
14import { interactive } from "./interactive"
15import merge from 'ts-deepmerge';
16export default function workspace(colorScheme: ColorScheme) {
17 const layer = colorScheme.lowest
18 const isLight = colorScheme.isLight
19 const itemSpacing = 8
20 const titlebarButton = toggleable(interactive({
21 base: {
22 cornerRadius: 6,
23 padding: {
24 top: 1,
25 bottom: 1,
26 left: 8,
27 right: 8,
28 },
29 ...text(layer, "sans", "variant", { size: "xs" }),
30 background: background(layer, "variant"),
31 border: border(layer),
32 }, state: {
33 hovered: {
34 ...text(layer, "sans", "variant", "hovered", { size: "xs" }),
35 background: background(layer, "variant", "hovered"),
36 border: border(layer, "variant", "hovered"),
37 },
38 clicked: {
39 ...text(layer, "sans", "variant", "pressed", { size: "xs" }),
40 background: background(layer, "variant", "pressed"),
41 border: border(layer, "variant", "pressed"),
42 }
43 }
44 }),
45 {
46 default: {
47 ...text(layer, "sans", "variant", "active", { size: "xs" }),
48 background: background(layer, "variant", "active"),
49 border: border(layer, "variant", "active"),
50 }
51 },
52 );
53 const avatarWidth = 18
54 const avatarOuterWidth = avatarWidth + 4
55 const followerAvatarWidth = 14
56 const followerAvatarOuterWidth = followerAvatarWidth + 4
57
58 return {
59 background: background(colorScheme.lowest),
60 blankPane: {
61 logoContainer: {
62 width: 256,
63 height: 256,
64 },
65 logo: svg(
66 withOpacity("#000000", colorScheme.isLight ? 0.6 : 0.8),
67 "icons/logo_96.svg",
68 256,
69 256
70 ),
71
72 logoShadow: svg(
73 withOpacity(
74 colorScheme.isLight
75 ? "#FFFFFF"
76 : colorScheme.lowest.base.default.background,
77 colorScheme.isLight ? 1 : 0.6
78 ),
79 "icons/logo_96.svg",
80 256,
81 256
82 ),
83 keyboardHints: {
84 margin: {
85 top: 96,
86 },
87 cornerRadius: 4,
88 },
89 keyboardHint:
90 interactive({
91 base: {
92 ...text(layer, "sans", "variant", { size: "sm" }),
93 padding: {
94 top: 3,
95 left: 8,
96 right: 8,
97 bottom: 3,
98 },
99 cornerRadius: 8
100 }, state: {
101 hovered: {
102 ...text(layer, "sans", "active", { size: "sm" }),
103 }
104 }
105 }),
106
107 keyboardHintWidth: 320,
108 },
109 joiningProjectAvatar: {
110 cornerRadius: 40,
111 width: 80,
112 },
113 joiningProjectMessage: {
114 padding: 12,
115 ...text(layer, "sans", { size: "lg" }),
116 },
117 externalLocationMessage: {
118 background: background(colorScheme.middle, "accent"),
119 border: border(colorScheme.middle, "accent"),
120 cornerRadius: 6,
121 padding: 12,
122 margin: { bottom: 8, right: 8 },
123 ...text(colorScheme.middle, "sans", "accent", { size: "xs" }),
124 },
125 leaderBorderOpacity: 0.7,
126 leaderBorderWidth: 2.0,
127 tabBar: tabBar(colorScheme),
128 modal: {
129 margin: {
130 bottom: 52,
131 top: 52,
132 },
133 cursor: "Arrow",
134 },
135 zoomedBackground: {
136 cursor: "Arrow",
137 background: isLight
138 ? withOpacity(background(colorScheme.lowest), 0.8)
139 : withOpacity(background(colorScheme.highest), 0.6),
140 },
141 zoomedPaneForeground: {
142 margin: 16,
143 shadow: colorScheme.modalShadow,
144 border: border(colorScheme.lowest, { overlay: true }),
145 },
146 zoomedPanelForeground: {
147 margin: 16,
148 border: border(colorScheme.lowest, { overlay: true }),
149 },
150 dock: {
151 left: {
152 border: border(layer, { right: true }),
153 },
154 bottom: {
155 border: border(layer, { top: true }),
156 },
157 right: {
158 border: border(layer, { left: true }),
159 },
160 },
161 paneDivider: {
162 color: borderColor(layer),
163 width: 1,
164 },
165 statusBar: statusBar(colorScheme),
166 titlebar: {
167 itemSpacing,
168 facePileSpacing: 2,
169 height: 33, // 32px + 1px border. It's important the content area of the titlebar is evenly sized to vertically center avatar images.
170 background: background(layer),
171 border: border(layer, { bottom: true }),
172 padding: {
173 left: 80,
174 right: itemSpacing,
175 },
176
177 // Project
178 title: text(layer, "sans", "variant"),
179 highlight_color: text(layer, "sans", "active").color,
180
181 // Collaborators
182 leaderAvatar: {
183 width: avatarWidth,
184 outerWidth: avatarOuterWidth,
185 cornerRadius: avatarWidth / 2,
186 outerCornerRadius: avatarOuterWidth / 2,
187 },
188 followerAvatar: {
189 width: followerAvatarWidth,
190 outerWidth: followerAvatarOuterWidth,
191 cornerRadius: followerAvatarWidth / 2,
192 outerCornerRadius: followerAvatarOuterWidth / 2,
193 },
194 inactiveAvatarGrayscale: true,
195 followerAvatarOverlap: 8,
196 leaderSelection: {
197 margin: {
198 top: 4,
199 bottom: 4,
200 },
201 padding: {
202 left: 2,
203 right: 2,
204 top: 2,
205 bottom: 2,
206 },
207 cornerRadius: 6,
208 },
209 avatarRibbon: {
210 height: 3,
211 width: 12,
212 // TODO: Chore: Make avatarRibbon colors driven by the theme rather than being hard coded.
213 },
214
215 // Sign in buttom
216 // FlatButton, Variant
217 signInPrompt:
218 merge(titlebarButton,
219 {
220 inactive: {
221 default: {
222 margin: {
223 left: itemSpacing,
224 },
225 }
226 }
227 }),
228
229
230 // Offline Indicator
231 offlineIcon: {
232 color: foreground(layer, "variant"),
233 width: 16,
234 margin: {
235 left: itemSpacing,
236 },
237 padding: {
238 right: 4,
239 },
240 },
241
242 // Notice that the collaboration server is out of date
243 outdatedWarning: {
244 ...text(layer, "sans", "warning", { size: "xs" }),
245 background: withOpacity(background(layer, "warning"), 0.3),
246 border: border(layer, "warning"),
247 margin: {
248 left: itemSpacing,
249 },
250 padding: {
251 left: 8,
252 right: 8,
253 },
254 cornerRadius: 6,
255 },
256 callControl: interactive({
257 base: {
258 cornerRadius: 6,
259 color: foreground(layer, "variant"),
260 iconWidth: 12,
261 buttonWidth: 20,
262 }, state: {
263 hovered: {
264 background: background(layer, "variant", "hovered"),
265 color: foreground(layer, "variant", "hovered"),
266 },
267 }
268 }),
269 toggleContactsButton: toggleable(interactive({
270 base: {
271 margin: { left: itemSpacing },
272 cornerRadius: 6,
273 color: foreground(layer, "variant"),
274 iconWidth: 14,
275 buttonWidth: 20,
276 },
277 state: {
278 clicked: {
279 background: background(layer, "variant", "pressed"),
280 color: foreground(layer, "variant", "pressed"),
281 },
282 hovered: {
283 background: background(layer, "variant", "hovered"),
284 color: foreground(layer, "variant", "hovered"),
285 }
286 }
287 }),
288 {
289 default: {
290 background: background(layer, "variant", "active"),
291 color: foreground(layer, "variant", "active")
292 }
293 },
294 ),
295 userMenuButton: merge(titlebarButton, {
296 inactive: {
297 default: {
298 buttonWidth: 20,
299 iconWidth: 12
300 }
301 }, active: { // posiewic: these properties are not currently set on main
302 default: {
303 iconWidth: 12,
304 button_width: 20,
305 }
306 }
307 }),
308
309
310 toggleContactsBadge: {
311 cornerRadius: 3,
312 padding: 2,
313 margin: { top: 3, left: 3 },
314 border: border(layer),
315 background: foreground(layer, "accent"),
316 },
317 shareButton: {
318 ...titlebarButton,
319 },
320 },
321
322 toolbar: {
323 height: 34,
324 background: background(colorScheme.highest),
325 border: border(colorScheme.highest, { bottom: true }),
326 itemSpacing: 8,
327 navButton: interactive(
328 {
329 base: {
330 color: foreground(colorScheme.highest, "on"),
331 iconWidth: 12,
332 buttonWidth: 24,
333 cornerRadius: 6,
334 }, state: {
335 hovered: {
336 color: foreground(colorScheme.highest, "on", "hovered"),
337 background: background(
338 colorScheme.highest,
339 "on",
340 "hovered"
341 ),
342 },
343 disabled: {
344 color: foreground(colorScheme.highest, "on", "disabled"),
345 },
346 }
347 }),
348 padding: { left: 8, right: 8, top: 4, bottom: 4 },
349 },
350 breadcrumbHeight: 24,
351 breadcrumbs: interactive({
352 base: {
353 ...text(colorScheme.highest, "sans", "variant"),
354 cornerRadius: 6,
355 padding: {
356 left: 6,
357 right: 6,
358 }
359 }, state: {
360 hovered: {
361 color: foreground(colorScheme.highest, "on", "hovered"),
362 background: background(colorScheme.highest, "on", "hovered"),
363 },
364 }
365 }),
366 disconnectedOverlay: {
367 ...text(layer, "sans"),
368 background: withOpacity(background(layer), 0.8),
369 },
370 notification: {
371 margin: { top: 10 },
372 background: background(colorScheme.middle),
373 cornerRadius: 6,
374 padding: 12,
375 border: border(colorScheme.middle),
376 shadow: colorScheme.popoverShadow,
377 },
378 notifications: {
379 width: 400,
380 margin: { right: 10, bottom: 10 },
381 },
382 dropTargetOverlayColor: withOpacity(foreground(layer, "variant"), 0.5),
383 }
384}