workspace.ts

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