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