From 8b33a58076e5a0c2b41a58f2e34d5c9a6ebe5310 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Tue, 29 Mar 2022 16:28:19 -0600 Subject: [PATCH] Express workspace in terms of new components Co-Authored-By: Nate Butler <1714999+iamnbutler@users.noreply.github.com> --- styles/app.ts | 155 +++------------------------------------ styles/components.ts | 23 +++++- styles/core.color.ts | 93 ----------------------- styles/core.ts | 26 +++++-- styles/lib.ts | 44 +++++++++++ styles/package-lock.json | 11 +++ styles/package.json | 1 + styles/selector-modal.ts | 2 +- styles/theme.ts | 46 ++++++++++++ styles/workspace.ts | 133 +++++++++++++++++++++++++++++++++ 10 files changed, 288 insertions(+), 246 deletions(-) delete mode 100644 styles/core.color.ts create mode 100644 styles/lib.ts create mode 100644 styles/workspace.ts diff --git a/styles/app.ts b/styles/app.ts index a7ae4348be..4f40577ae9 100644 --- a/styles/app.ts +++ b/styles/app.ts @@ -1,147 +1,12 @@ -import { selectorModal } from "./selector-modal"; +import { backgroundColor } from "./components"; +import selectorModal from "./selector-modal"; +import workspace from "./workspace"; import Theme from "./theme"; export default function app(theme: Theme): Object { return { selector: selectorModal(theme), - workspace: { - background: "$surface.500", - leaderBorderOpacity: 0.7, - leader_border_width: 2.0, - active_tab: { - background: "$surface.300", - extends: "$workspace.tab", - text: "$text.primary", - border: { - bottom: false, - }, - }, - left_sidebar: { - extends: "$workspace.sidebar", - border: { - color: "$border.primary", - right: true, - width: 1, - }, - }, - pane_divider: { - color: "$border.primary", - width: 1, - }, - right_sidebar: { - extends: "$workspace.sidebar", - border: { - color: "$border.primary", - left: true, - width: 1, - }, - }, - sidebar: { - width: 30, - active_item: { - extends: "$workspace.sidebar.item", - icon_color: "$text.primary.color", - }, - border: { - color: "$border.primary", - right: true, - width: 1, - }, - item: { - height: "$workspace.tab.height", - icon_color: "$text.muted.color", - icon_size: 18, - }, - resize_handle: { - background: "$border.primary", - padding: { - left: 1, - }, - }, - }, - status_bar: { - cursor_position: "$text.muted", - diagnostic_message: "$text.muted", - height: 24, - item_spacing: 8, - lsp_message: "$text.muted", - padding: { - left: 6, - right: 6, - }, - }, - tab: { - height: 34, - icon_close: "$text.muted.color", - icon_close_active: "$text.primary.color", - icon_conflict: "$status.warn", - icon_dirty: "$status.info", - icon_width: 8, - spacing: 10, - text: "$text.muted", - border: { - bottom: true, - color: "$border.primary", - left: true, - overlay: true, - width: 1, - }, - padding: { - left: 12, - right: 12, - }, - }, - titlebar: { - avatar_width: 18, - height: 32, - share_icon_active_color: "$text.primary.color", - share_icon_color: "$text.muted.color", - title: "$text.primary", - avatar: { - corner_radius: 10, - border: { - color: "#00000088", - width: 1, - }, - }, - avatar_ribbon: { - background: "#ff0000", - height: 3, - width: 12, - }, - border: { - bottom: true, - color: "$border.primary", - width: 1, - }, - hovered_sign_in_prompt: { - color: "$text.secondary.color", - extends: "$workspace.titlebar.sign_in_prompt", - }, - offline_icon: { - color: "$text.muted.color", - width: 16, - padding: { - right: 4, - }, - }, - outdated_warning: { - extends: "$text.muted", - size: 13, - }, - sign_in_prompt: { - extends: "$text.muted", - size: 13, - underline: true, - padding: { - right: 8, - }, - }, - }, - toolbar: { - height: 44, - }, - }, + workspace: workspace(theme), chat_panel: { extends: "$panel", channel_name: { @@ -205,7 +70,7 @@ export default function app(theme: Theme): Object { extends: "$chat_panel.sign_in_prompt", }, input_editor: { - background: "$surface.300", + background: backgroundColor(theme, 300), corner_radius: 6, placeholder_text: "$text.muted", selection: "$selection.host", @@ -306,7 +171,7 @@ export default function app(theme: Theme): Object { }, editor: { active_line_background: "$state.active_line", - background: "$surface.300", + background: backgroundColor(theme, 300), code_actions_indicator: "$text.muted.color", diff_background_deleted: "$state.deleted_line", diff_background_inserted: "$state.inserted_line", @@ -314,7 +179,7 @@ export default function app(theme: Theme): Object { document_highlight_write_background: "#99999916", error_color: "$status.bad", guest_selections: "$selection.guests", - gutter_background: "$surface.300", + gutter_background: backgroundColor(theme, 300), gutter_padding_factor: 2.5, highlighted_line_background: "$state.highlighted_line", line_number: "$text.muted.color", @@ -502,7 +367,7 @@ export default function app(theme: Theme): Object { }, }, project_diagnostics: { - background: "$surface.300", + background: backgroundColor(theme, 300), tab_icon_spacing: 4, tab_icon_width: 13, tab_summary_spacing: 10, @@ -547,7 +412,7 @@ export default function app(theme: Theme): Object { }, }, search: { - background: "$surface.300", + background: backgroundColor(theme, 300), match_background: "$state.highlighted_line", tab_icon_spacing: 4, tab_icon_width: 14, @@ -599,7 +464,7 @@ export default function app(theme: Theme): Object { padding: 6, }, option_button: { - background: "$surface.300", + background: backgroundColor(theme, 300), corner_radius: 6, extends: "$text.secondary", border: { diff --git a/styles/components.ts b/styles/components.ts index 226d1d9e37..9cc58046ff 100644 --- a/styles/components.ts +++ b/styles/components.ts @@ -1,5 +1,6 @@ import chroma from "chroma-js"; -import core, { Color } from "./core"; +import core from "./core"; +import { Color } from "./lib"; import Theme, { BackgroundColor, Weight } from "./theme"; export function text( @@ -19,13 +20,31 @@ export function text( }; } -export function border(theme: Theme, color: keyof Theme["borderColor"]) { +export interface BorderOptions { + width?: number; + top?: boolean; + bottom?: boolean; + left?: boolean; + right?: boolean; + overlay?: boolean; +} + +export function border( + theme: Theme, + color: keyof Theme["borderColor"], + options?: BorderOptions +) { return { color: theme.borderColor[color].value, width: 1, + ...options, }; } +export function iconColor(theme: Theme, color: keyof Theme["iconColor"]) { + return theme.iconColor[color].value; +} + export interface Player { selection: { cursor: Color; diff --git a/styles/core.color.ts b/styles/core.color.ts deleted file mode 100644 index 004e7209a2..0000000000 --- a/styles/core.color.ts +++ /dev/null @@ -1,93 +0,0 @@ -import chroma from "chroma-js"; - -export type Color = string; - -function returnTokens( - colorName: string, - ramp: Array, // help, have no clue on type here -) { - let tokens = {}; - let token = {}; - let colorNumber = 0; - let increment = 0; - - for (let i = 0; i < ramp.len; i++) { - if (i > 11 ) { - increment = 50; - } else { - increment = 100; - } - - if (i !== 0) { - colorNumber = i * increment; - } - - token = { - [`${colorName}_${colorNumber}`]: { - value: ramp[i].value, - step: i, - type: "color", - }, - }; - - Object.assign(token, tokens); - } - return tokens; -} - -function oneColorRamp( - colorName: string, - baseColor: string, - steps: number = 10 -) { - let hsl = chroma(baseColor).hsl(); - let h = Math.round(hsl[0]); - let lightColor = chroma.hsl(h, 0.88, 0.96).hex(); - let darkColor = chroma.hsl(h, 0.68, 0.32).hex(); - - let ramp = chroma - .scale([lightColor, baseColor, darkColor]) - .domain([0, 0.5, 1]) - .mode("hsl") - .gamma(1) - .correctLightness(true) - .padding([0, 0.15]) - .colors(steps) - .hex(); - - return returnTokens(colorName, ramp); -} - -function colorRamp( - colorName: string, - startColor: string, - endColor: string, - steps: number -) { - let ramp = chroma.scale([startColor, endColor]).mode("hsl").colors(steps).hex(); - - return returnTokens(colorName, ramp); -} - -export default { - color: { - neutral: colorRamp("neutral", "black", "white", 21), // colorName, startColor, endColor, steps - rose: oneColorRamp("rose", "#F43F5EFF"), // colorName, baseColor, steps(optional) - red: oneColorRamp("red", "#EF4444FF"), - orange: oneColorRamp("orange", "#F97316FF"), - amber: oneColorRamp("amber", "#F59E0BFF"), - yellow: oneColorRamp("yellow", "#EAB308FF"), - lime: oneColorRamp("lime", "#84CC16FF"), - green: oneColorRamp("green", "#22C55EFF"), - emerald: oneColorRamp("emerald", "#10B981FF"), - teal: oneColorRamp("teal", "#14B8A6FF"), - cyan: oneColorRamp("cyan", "#06BBD4FF"), - sky: oneColorRamp("sky", "#0EA5E9FF"), - blue: oneColorRamp("blue", "#3B82F6FF"), - indigo: oneColorRamp("indigo", "#6366F1FF"), - violet: oneColorRamp("violet", "#8B5CF6FF"), - purple: oneColorRamp("purple", "#A855F7FF"), - fuschia: oneColorRamp("fuschia", "#D946E4FF"), - pink: oneColorRamp("pink", "#EC4899FF"), - }, -}; diff --git a/styles/core.ts b/styles/core.ts index 6444ef9a1c..e9e81982e4 100644 --- a/styles/core.ts +++ b/styles/core.ts @@ -1,10 +1,6 @@ -import color from "./core.color"; - -export type Color = string; +import { colorRamp } from "./lib"; export default { - color: color, - fontFamily: { sans: "Zed Sans", mono: "Zed Mono", @@ -39,4 +35,24 @@ export default { type: "fontSizes", }, }, + color: { + neutral: colorRamp(["black", "white"], { steps: 21, increment: 50 }), + rose: colorRamp("#F43F5EFF"), + red: colorRamp("#EF4444FF"), + orange: colorRamp("#F97316FF"), + amber: colorRamp("#F59E0BFF"), + yellow: colorRamp("#EAB308FF"), + lime: colorRamp("#84CC16FF"), + green: colorRamp("#22C55EFF"), + emerald: colorRamp("#10B981FF"), + teal: colorRamp("#14B8A6FF"), + cyan: colorRamp("#06BBD4FF"), + sky: colorRamp("#0EA5E9FF"), + blue: colorRamp("#3B82F6FF"), + indigo: colorRamp("#6366F1FF"), + violet: colorRamp("#8B5CF6FF"), + purple: colorRamp("#A855F7FF"), + fuschia: colorRamp("#D946E4FF"), + pink: colorRamp("#EC4899FF"), + }, }; diff --git a/styles/lib.ts b/styles/lib.ts new file mode 100644 index 0000000000..b59f4fa694 --- /dev/null +++ b/styles/lib.ts @@ -0,0 +1,44 @@ +import chroma, { Scale } from "chroma-js"; + +export type Color = string; +export type ColorRampStep = { value: Color; type: "color"; step: number }; +export type ColorRamp = { + [index: number]: ColorRampStep; +}; + +export function colorRamp( + color: Color | [Color, Color], + options?: { steps?: number; increment?: number } +): ColorRamp { + let scale: Scale; + if (Array.isArray(color)) { + const [startColor, endColor] = color; + scale = chroma.scale([startColor, endColor]); + } else { + let hue = Math.round(chroma(color).hsl()[0]); + let startColor = chroma.hsl(hue, 0.88, 0.96); + let endColor = chroma.hsl(hue, 0.68, 0.32); + scale = chroma + .scale([startColor, color, endColor]) + .domain([0, 0.5, 1]) + .mode("hsl") + .gamma(1) + .correctLightness(true) + .padding([0, 0.15]); + } + + const ramp: ColorRamp = {}; + const steps = options?.steps || 10; + const increment = options?.increment || 100; + + scale.colors(steps, "hex").forEach((color, ix) => { + const step = ix * increment; + ramp[step] = { + value: color, + step, + type: "color", + }; + }); + + return ramp; +} diff --git a/styles/package-lock.json b/styles/package-lock.json index 3abb465628..7b8503bf72 100644 --- a/styles/package-lock.json +++ b/styles/package-lock.json @@ -9,9 +9,15 @@ "version": "1.0.0", "license": "ISC", "dependencies": { + "@types/chroma-js": "^2.1.3", "chroma-js": "^2.4.2" } }, + "node_modules/@types/chroma-js": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@types/chroma-js/-/chroma-js-2.1.3.tgz", + "integrity": "sha512-1xGPhoSGY1CPmXLCBcjVZSQinFjL26vlR8ZqprsBWiFyED4JacJJ9zHhh5aaUXqbY9B37mKQ73nlydVAXmr1+g==" + }, "node_modules/chroma-js": { "version": "2.4.2", "resolved": "https://registry.npmjs.org/chroma-js/-/chroma-js-2.4.2.tgz", @@ -19,6 +25,11 @@ } }, "dependencies": { + "@types/chroma-js": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@types/chroma-js/-/chroma-js-2.1.3.tgz", + "integrity": "sha512-1xGPhoSGY1CPmXLCBcjVZSQinFjL26vlR8ZqprsBWiFyED4JacJJ9zHhh5aaUXqbY9B37mKQ73nlydVAXmr1+g==" + }, "chroma-js": { "version": "2.4.2", "resolved": "https://registry.npmjs.org/chroma-js/-/chroma-js-2.4.2.tgz", diff --git a/styles/package.json b/styles/package.json index 92f0546c56..c66da8718b 100644 --- a/styles/package.json +++ b/styles/package.json @@ -9,6 +9,7 @@ "author": "", "license": "ISC", "dependencies": { + "@types/chroma-js": "^2.1.3", "chroma-js": "^2.4.2" } } diff --git a/styles/selector-modal.ts b/styles/selector-modal.ts index f7101c9151..ddba32683a 100644 --- a/styles/selector-modal.ts +++ b/styles/selector-modal.ts @@ -1,7 +1,7 @@ import { backgroundColor, border, player, shadow, text } from "./components"; import Theme from "./theme"; -export function selectorModal(theme: Theme): Object { +export default function selectorModal(theme: Theme): Object { const item = { padding: { bottom: 4, diff --git a/styles/theme.ts b/styles/theme.ts index 5363a8c01c..ddfa6414f4 100644 --- a/styles/theme.ts +++ b/styles/theme.ts @@ -1,3 +1,5 @@ +import { colorRamp } from "./lib"; + export type Color = string; export type Weight = | "thin" @@ -87,6 +89,50 @@ export default interface Theme { feature: { value: Color; }; + ok: { + value: Color; + }; + error: { + value: Color; + }; + warning: { + value: Color; + }; + info: { + value: Color; + }; + }; + iconColor: { + primary: { + value: Color; + }; + secondary: { + value: Color; + }; + muted: { + value: Color; + }; + placeholder: { + value: Color; + }; + active: { + value: Color; + }; + feature: { + value: Color; + }; + ok: { + value: Color; + }; + error: { + value: Color; + }; + warning: { + value: Color; + }; + info: { + value: Color; + }; }; syntax: { primary: SyntaxHighlightStyle; diff --git a/styles/workspace.ts b/styles/workspace.ts new file mode 100644 index 0000000000..5ecb3a378c --- /dev/null +++ b/styles/workspace.ts @@ -0,0 +1,133 @@ +import { backgroundColor, border, iconColor, text } from "./components"; +import Theme from "./theme"; + +export default function workspace(theme: Theme) { + const signInPrompt = { + ...text(theme, "sans", "secondary"), + size: 13, + underline: true, + padding: { + right: 8, + }, + }; + + const tab = { + height: 34, + iconClose: iconColor(theme, "secondary"), + iconCloseActive: iconColor(theme, "active"), + iconConflict: iconColor(theme, "warning"), + iconDirty: iconColor(theme, "info"), + iconWidth: 8, + spacing: 10, + text: text(theme, "mono", "secondary"), + border: border(theme, "primary", { + left: true, + bottom: true, + overlay: true, + }), + padding: { + left: 12, + right: 12, + }, + }; + + const activeTab = { + ...tab, + background: backgroundColor(theme, 300), + text: text(theme, "mono", "primary"), + border: { + ...tab.border, + bottom: false, + }, + }; + + const sidebarItem = { + height: "$workspace.tab.height", + iconColor: "$text.muted.color", + iconSize: 18, + }; + const sidebar = { + width: 30, + border: border(theme, "primary", { right: true }), + item: sidebarItem, + activeItem: { + ...sidebarItem, + iconColor: iconColor(theme, "primary"), + }, + resizeHandle: { + background: border(theme, "primary").color, + padding: { + left: 1, + }, + }, + }; + + return { + background: backgroundColor(theme, 500), + leaderBorderOpacity: 0.7, + leaderBorderWidth: 2.0, + tab, + activeTab, + leftSidebar: { + ...sidebar, + border: border(theme, "primary", { right: true }), + }, + rightSidebar: { + ...sidebar, + border: border(theme, "primary", { left: true }), + }, + paneDivider: { + color: border(theme, "primary").color, + width: 1, + }, + status_bar: { + height: 24, + itemSpacing: 8, + padding: { + left: 6, + right: 6, + }, + cursorPosition: text(theme, "sans", "muted"), + diagnosticMessage: text(theme, "sans", "muted"), + lspMessage: text(theme, "sans", "muted"), + }, + titlebar: { + avatarWidth: 18, + height: 32, + shareIconColor: iconColor(theme, "secondary"), + shareIconActiveColor: iconColor(theme, "active"), + title: text(theme, "sans", "primary"), + avatar: { + cornerRadius: 10, + border: { + color: "#00000088", + width: 1, + }, + }, + avatarRibbon: { + height: 3, + width: 12, + }, + border: border(theme, "primary", { bottom: true }), + signInPrompt, + hoveredSignInPrompt: { + ...signInPrompt, + ...text(theme, "mono", "active"), + }, + offlineIcon: { + color: iconColor(theme, "muted"), + width: 16, + padding: { + right: 4, + }, + }, + outdatedWarning: { + ...text(theme, "sans", "muted"), + size: 13, + }, + }, + toolbar: { + height: 44, + }, + }; +}