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            userMenuButton: merge(titlebarButton, {
347                inactive: {
348                    default: {
349                        buttonWidth: 20,
350                        iconWidth: 12,
351                    },
352                },
353                active: {
354                    default: {
355                        iconWidth: 12,
356                        button_width: 20,
357                        background: background(layer, "variant", "active"),
358                        color: foreground(layer, "variant", "active"),
359                    }
360                },
361            }),
362
363            toggleContactsBadge: {
364                cornerRadius: 3,
365                padding: 2,
366                margin: { top: 3, left: 3 },
367                border: border(layer),
368                background: foreground(layer, "accent"),
369            },
370            shareButton: {
371                ...titlebarButton,
372            },
373        },
374
375        toolbar: {
376            height: 34,
377            background: background(colorScheme.highest),
378            border: border(colorScheme.highest, { bottom: true }),
379            itemSpacing: 8,
380            navButton: interactive({
381                base: {
382                    color: foreground(colorScheme.highest, "on"),
383                    iconWidth: 12,
384                    buttonWidth: 24,
385                    cornerRadius: 6,
386                },
387                state: {
388                    hovered: {
389                        color: foreground(colorScheme.highest, "on", "hovered"),
390                        background: background(
391                            colorScheme.highest,
392                            "on",
393                            "hovered"
394                        ),
395                    },
396                    disabled: {
397                        color: foreground(
398                            colorScheme.highest,
399                            "on",
400                            "disabled"
401                        ),
402                    },
403                },
404            }),
405            padding: { left: 8, right: 8, top: 4, bottom: 4 },
406        },
407        breadcrumbHeight: 24,
408        breadcrumbs: interactive({
409            base: {
410                ...text(colorScheme.highest, "sans", "variant"),
411                cornerRadius: 6,
412                padding: {
413                    left: 6,
414                    right: 6,
415                },
416            },
417            state: {
418                hovered: {
419                    color: foreground(colorScheme.highest, "on", "hovered"),
420                    background: background(
421                        colorScheme.highest,
422                        "on",
423                        "hovered"
424                    ),
425                },
426            },
427        }),
428        disconnectedOverlay: {
429            ...text(layer, "sans"),
430            background: withOpacity(background(layer), 0.8),
431        },
432        notification: {
433            margin: { top: 10 },
434            background: background(colorScheme.middle),
435            cornerRadius: 6,
436            padding: 12,
437            border: border(colorScheme.middle),
438            shadow: colorScheme.popoverShadow,
439        },
440        notifications: {
441            width: 400,
442            margin: { right: 10, bottom: 10 },
443        },
444        dropTargetOverlayColor: withOpacity(foreground(layer, "variant"), 0.5),
445    }
446}