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