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