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                                color: foreground(layer, "variant", "pressed"),
291                            },
292                            hovered: {
293                                background: background(layer, "variant", "hovered"),
294                                color: foreground(layer, "variant", "hovered"),
295                            },
296                        },
297                    }), state:
298                {
299                    active: {
300                        default: {
301                            background: background(layer, "variant", "active"),
302                            color: foreground(layer, "variant", "active"),
303                        },
304                    }
305                }
306            }
307            ),
308            userMenuButton: merge(titlebarButton, {
309                inactive: {
310                    default: {
311                        buttonWidth: 20,
312                        iconWidth: 12,
313                    },
314                },
315                active: {
316                    // posiewic: these properties are not currently set on main
317                    default: {
318                        iconWidth: 12,
319                        button_width: 20,
320                    },
321                },
322            }),
323
324            toggleContactsBadge: {
325                cornerRadius: 3,
326                padding: 2,
327                margin: { top: 3, left: 3 },
328                border: border(layer),
329                background: foreground(layer, "accent"),
330            },
331            shareButton: {
332                ...titlebarButton,
333            },
334        },
335
336        toolbar: {
337            height: 34,
338            background: background(colorScheme.highest),
339            border: border(colorScheme.highest, { bottom: true }),
340            itemSpacing: 8,
341            navButton: interactive({
342                base: {
343                    color: foreground(colorScheme.highest, "on"),
344                    iconWidth: 12,
345                    buttonWidth: 24,
346                    cornerRadius: 6,
347                },
348                state: {
349                    hovered: {
350                        color: foreground(colorScheme.highest, "on", "hovered"),
351                        background: background(
352                            colorScheme.highest,
353                            "on",
354                            "hovered"
355                        ),
356                    },
357                    disabled: {
358                        color: foreground(
359                            colorScheme.highest,
360                            "on",
361                            "disabled"
362                        ),
363                    },
364                },
365            }),
366            padding: { left: 8, right: 8, top: 4, bottom: 4 },
367        },
368        breadcrumbHeight: 24,
369        breadcrumbs: interactive({
370            base: {
371                ...text(colorScheme.highest, "sans", "variant"),
372                cornerRadius: 6,
373                padding: {
374                    left: 6,
375                    right: 6,
376                },
377            },
378            state: {
379                hovered: {
380                    color: foreground(colorScheme.highest, "on", "hovered"),
381                    background: background(
382                        colorScheme.highest,
383                        "on",
384                        "hovered"
385                    ),
386                },
387            },
388        }),
389        disconnectedOverlay: {
390            ...text(layer, "sans"),
391            background: withOpacity(background(layer), 0.8),
392        },
393        notification: {
394            margin: { top: 10 },
395            background: background(colorScheme.middle),
396            cornerRadius: 6,
397            padding: 12,
398            border: border(colorScheme.middle),
399            shadow: colorScheme.popoverShadow,
400        },
401        notifications: {
402            width: 400,
403            margin: { right: 10, bottom: 10 },
404        },
405        dropTargetOverlayColor: withOpacity(foreground(layer, "variant"), 0.5),
406    }
407}