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 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}