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