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