workspace.ts

  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 signInButton = toggleable({
 62        base: interactive({
 63            base: {
 64                cornerRadius: 6,
 65                padding: {
 66                    top: 1,
 67                    bottom: 1,
 68                    left: 8,
 69                    right: 8,
 70                },
 71                ...text(layer, "sans", "variant", { size: "xs" }),
 72                background: background(layer, "variant"),
 73            },
 74            state: {
 75                hovered: {
 76                    ...text(layer, "sans", "variant", "hovered", { size: "xs" }),
 77                    background: background(layer, "variant", "hovered"),
 78                    //border: border(layer, "variant", "hovered"),
 79                },
 80                clicked: {
 81                    ...text(layer, "sans", "variant", "pressed", { size: "xs" }),
 82                    background: background(layer, "variant", "pressed"),
 83                    //border: border(layer, "variant", "pressed"),
 84                }
 85            }
 86        }),
 87        state: {
 88            active: {
 89                default: {
 90                    ...text(layer, "sans", "variant", "active", { size: "xs" }),
 91                    background: background(layer, "variant", "active"),
 92                    //border: border(layer, "variant", "active"),
 93                }
 94            },
 95        }
 96    });
 97    const avatarWidth = 18
 98    const avatarOuterWidth = avatarWidth + 4
 99    const followerAvatarWidth = 14
100    const followerAvatarOuterWidth = followerAvatarWidth + 4
101
102    return {
103        background: background(colorScheme.lowest),
104        blankPane: {
105            logoContainer: {
106                width: 256,
107                height: 256,
108            },
109            logo: svg(
110                withOpacity("#000000", colorScheme.isLight ? 0.6 : 0.8),
111                "icons/logo_96.svg",
112                256,
113                256
114            ),
115
116            logoShadow: svg(
117                withOpacity(
118                    colorScheme.isLight
119                        ? "#FFFFFF"
120                        : colorScheme.lowest.base.default.background,
121                    colorScheme.isLight ? 1 : 0.6
122                ),
123                "icons/logo_96.svg",
124                256,
125                256
126            ),
127            keyboardHints: {
128                margin: {
129                    top: 96,
130                },
131                cornerRadius: 4,
132            },
133            keyboardHint: interactive({
134                base: {
135                    ...text(layer, "sans", "variant", { size: "sm" }),
136                    padding: {
137                        top: 3,
138                        left: 8,
139                        right: 8,
140                        bottom: 3,
141                    },
142                    cornerRadius: 8,
143                },
144                state: {
145                    hovered: {
146                        ...text(layer, "sans", "active", { size: "sm" }),
147                    },
148                },
149            }),
150
151            keyboardHintWidth: 320,
152        },
153        joiningProjectAvatar: {
154            cornerRadius: 40,
155            width: 80,
156        },
157        joiningProjectMessage: {
158            padding: 12,
159            ...text(layer, "sans", { size: "lg" }),
160        },
161        externalLocationMessage: {
162            background: background(colorScheme.middle, "accent"),
163            border: border(colorScheme.middle, "accent"),
164            cornerRadius: 6,
165            padding: 12,
166            margin: { bottom: 8, right: 8 },
167            ...text(colorScheme.middle, "sans", "accent", { size: "xs" }),
168        },
169        leaderBorderOpacity: 0.7,
170        leaderBorderWidth: 2.0,
171        tabBar: tabBar(colorScheme),
172        modal: {
173            margin: {
174                bottom: 52,
175                top: 52,
176            },
177            cursor: "Arrow",
178        },
179        zoomedBackground: {
180            cursor: "Arrow",
181            background: isLight
182                ? withOpacity(background(colorScheme.lowest), 0.8)
183                : withOpacity(background(colorScheme.highest), 0.6),
184        },
185        zoomedPaneForeground: {
186            margin: 16,
187            shadow: colorScheme.modalShadow,
188            border: border(colorScheme.lowest, { overlay: true }),
189        },
190        zoomedPanelForeground: {
191            margin: 16,
192            border: border(colorScheme.lowest, { overlay: true }),
193        },
194        dock: {
195            left: {
196                border: border(layer, { right: true }),
197            },
198            bottom: {
199                border: border(layer, { top: true }),
200            },
201            right: {
202                border: border(layer, { left: true }),
203            },
204        },
205        paneDivider: {
206            color: borderColor(layer),
207            width: 1,
208        },
209        statusBar: statusBar(colorScheme),
210        titlebar: {
211            itemSpacing,
212            facePileSpacing: 2,
213            height: 33, // 32px + 1px border. It's important the content area of the titlebar is evenly sized to vertically center avatar images.
214            background: background(layer),
215            border: border(layer, { bottom: true }),
216            padding: {
217                left: 80,
218                right: itemSpacing,
219            },
220
221            // Project
222            title: text(layer, "sans", "variant"),
223            highlight_color: text(layer, "sans", "active").color,
224
225            // Collaborators
226            leaderAvatar: {
227                width: avatarWidth,
228                outerWidth: avatarOuterWidth,
229                cornerRadius: avatarWidth / 2,
230                outerCornerRadius: avatarOuterWidth / 2,
231            },
232            followerAvatar: {
233                width: followerAvatarWidth,
234                outerWidth: followerAvatarOuterWidth,
235                cornerRadius: followerAvatarWidth / 2,
236                outerCornerRadius: followerAvatarOuterWidth / 2,
237            },
238            inactiveAvatarGrayscale: true,
239            followerAvatarOverlap: 8,
240            leaderSelection: {
241                margin: {
242                    top: 4,
243                    bottom: 4,
244                },
245                padding: {
246                    left: 2,
247                    right: 2,
248                    top: 2,
249                    bottom: 2,
250                },
251                cornerRadius: 6,
252            },
253            avatarRibbon: {
254                height: 3,
255                width: 12,
256                // TODO: Chore: Make avatarRibbon colors driven by the theme rather than being hard coded.
257            },
258
259            // Sign in buttom
260            // FlatButton, Variant
261            signInPrompt: merge(titlebarButton, {
262                inactive: {
263                    default: {
264                        margin: {
265                            left: itemSpacing,
266                        },
267                    },
268                },
269
270                signInButton,
271
272            }),
273
274            // Offline Indicator
275            offlineIcon: {
276                color: foreground(layer, "variant"),
277                width: 16,
278                margin: {
279                    left: itemSpacing,
280                },
281                padding: {
282                    right: 4,
283                },
284            },
285
286            // Notice that the collaboration server is out of date
287            outdatedWarning: {
288                ...text(layer, "sans", "warning", { size: "xs" }),
289                background: withOpacity(background(layer, "warning"), 0.3),
290                border: border(layer, "warning"),
291                margin: {
292                    left: itemSpacing,
293                },
294                padding: {
295                    left: 8,
296                    right: 8,
297                },
298                cornerRadius: 6,
299            },
300            callControl: interactive({
301                base: {
302                    cornerRadius: 6,
303                    color: foreground(layer, "variant"),
304                    iconWidth: 12,
305                    buttonWidth: 20,
306                },
307                state: {
308                    hovered: {
309                        background: background(layer, "variant", "hovered"),
310                        color: foreground(layer, "variant", "hovered"),
311                    },
312                },
313            }),
314            toggleContactsButton: toggleable({
315                base: interactive({
316                    base: {
317                        margin: { left: itemSpacing },
318                        cornerRadius: 6,
319                        color: foreground(layer, "variant"),
320                        iconWidth: 14,
321                        buttonWidth: 20,
322                    },
323                    state: {
324                        clicked: {
325                            background: background(layer, "variant", "pressed"),
326                        },
327                        hovered: {
328                            background: background(layer, "variant", "hovered"),
329                        },
330                    },
331                }),
332                state: {
333                    active: {
334                        default: {
335                            background: background(layer, "on", "default"),
336                        },
337                        hovered: {
338                            background: background(layer, "on", "hovered"),
339                        },
340                        clicked: {
341                            background: background(layer, "on", "pressed"),
342                        },
343                    },
344                },
345            }),
346            toggleMicrophoneButton: toggleable({
347                base: interactive({
348                    base: {
349                        margin: { left: itemSpacing },
350                        cornerRadius: 6,
351                        color: foreground(layer, "variant"),
352                        iconWidth: 14,
353                        buttonWidth: 20,
354                    },
355                    state: {
356                        clicked: {
357                            background: background(layer, "variant", "pressed"),
358                        },
359                        hovered: {
360                            background: background(layer, "variant", "hovered"),
361                        },
362                    },
363                }),
364                state: {
365                    active: {
366                        default: {
367                            background: background(layer, "on", "default"),
368                        },
369                        hovered: {
370                            background: background(layer, "on", "hovered"),
371                        },
372                        clicked: {
373                            background: background(layer, "on", "pressed"),
374                        },
375                    },
376                },
377            }),
378            toggleSpeakersButton: toggleable({
379                base: interactive({
380                    base: {
381                        margin: { left: itemSpacing },
382                        cornerRadius: 6,
383                        color: foreground(layer, "variant"),
384                        iconWidth: 14,
385                        buttonWidth: 20,
386                    },
387                    state: {
388                        clicked: {
389                            background: background(layer, "variant", "pressed"),
390                        },
391                        hovered: {
392                            background: background(layer, "variant", "hovered"),
393                        },
394                    },
395                }),
396                state: {
397                    active: {
398                        default: {
399                            background: background(layer, "on", "default"),
400                        },
401                        hovered: {
402                            background: background(layer, "on", "hovered"),
403                        },
404                        clicked: {
405                            background: background(layer, "on", "pressed"),
406                        },
407                    },
408                },
409            }),
410            leaveCallButton: interactive({
411                base: {
412                    margin: { left: itemSpacing },
413                    cornerRadius: 6,
414                    color: foreground(layer, "variant"),
415                    iconWidth: 14,
416                    buttonWidth: 20,
417                },
418                state: {
419                    clicked: {
420                        background: background(layer, "variant", "pressed"),
421                    },
422                    hovered: {
423                        background: background(layer, "variant", "hovered"),
424                    },
425                },
426            }),
427
428            userMenuButton: merge(titlebarButton, {
429                inactive: {
430                    default: {
431                        buttonWidth: 20,
432                        iconWidth: 12,
433                    },
434                },
435                active: {
436                    default: {
437                        iconWidth: 12,
438                        button_width: 20,
439                        background: background(layer, "variant", "active"),
440                        color: foreground(layer, "variant", "active"),
441                    }
442                },
443            }),
444
445            toggleContactsBadge: {
446                cornerRadius: 3,
447                padding: 2,
448                margin: { top: 3, left: 3 },
449                border: border(layer),
450                background: foreground(layer, "accent"),
451            },
452            shareButton: {
453                ...titlebarButton,
454            },
455        },
456
457        toolbar: {
458            height: 34,
459            background: background(colorScheme.highest),
460            border: border(colorScheme.highest, { bottom: true }),
461            itemSpacing: 8,
462            navButton: interactive({
463                base: {
464                    color: foreground(colorScheme.highest, "on"),
465                    iconWidth: 12,
466                    buttonWidth: 24,
467                    cornerRadius: 6,
468                },
469                state: {
470                    hovered: {
471                        color: foreground(colorScheme.highest, "on", "hovered"),
472                        background: background(
473                            colorScheme.highest,
474                            "on",
475                            "hovered"
476                        ),
477                    },
478                    disabled: {
479                        color: foreground(
480                            colorScheme.highest,
481                            "on",
482                            "disabled"
483                        ),
484                    },
485                },
486            }),
487            padding: { left: 8, right: 8, top: 4, bottom: 4 },
488        },
489        breadcrumbHeight: 24,
490        breadcrumbs: interactive({
491            base: {
492                ...text(colorScheme.highest, "sans", "variant"),
493                cornerRadius: 6,
494                padding: {
495                    left: 6,
496                    right: 6,
497                },
498            },
499            state: {
500                hovered: {
501                    color: foreground(colorScheme.highest, "on", "hovered"),
502                    background: background(
503                        colorScheme.highest,
504                        "on",
505                        "hovered"
506                    ),
507                },
508            },
509        }),
510        disconnectedOverlay: {
511            ...text(layer, "sans"),
512            background: withOpacity(background(layer), 0.8),
513        },
514        notification: {
515            margin: { top: 10 },
516            background: background(colorScheme.middle),
517            cornerRadius: 6,
518            padding: 12,
519            border: border(colorScheme.middle),
520            shadow: colorScheme.popoverShadow,
521        },
522        notifications: {
523            width: 400,
524            margin: { right: 10, bottom: 10 },
525        },
526        dropTargetOverlayColor: withOpacity(foreground(layer, "variant"), 0.5),
527    }
528}