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