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