diff --git a/styles/package-lock.json b/styles/package-lock.json index 3f73a0b4e533899055b2a03e60938eb384e1e583..6fc5f746e52e93f16263d37f6d1ef57cebbf822f 100644 --- a/styles/package-lock.json +++ b/styles/package-lock.json @@ -27,7 +27,8 @@ "ts-node": "^10.9.1", "typescript": "^5.1.5", "utility-types": "^3.10.0", - "vitest": "^0.32.0" + "vitest": "^0.32.0", + "zustand": "^4.3.8" } }, "node_modules/@aashutoshrathi/word-wrap": { @@ -2595,6 +2596,12 @@ "node": ">= 0.8" } }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "peer": true + }, "node_modules/js-yaml": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", @@ -2706,6 +2713,18 @@ "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==" }, + "node_modules/loose-envify": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", + "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", + "peer": true, + "dependencies": { + "js-tokens": "^3.0.0 || ^4.0.0" + }, + "bin": { + "loose-envify": "cli.js" + } + }, "node_modules/loupe": { "version": "2.3.6", "resolved": "https://registry.npmjs.org/loupe/-/loupe-2.3.6.tgz", @@ -3292,6 +3311,18 @@ } ] }, + "node_modules/react": { + "version": "18.2.0", + "resolved": "https://registry.npmjs.org/react/-/react-18.2.0.tgz", + "integrity": "sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==", + "peer": true, + "dependencies": { + "loose-envify": "^1.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/react-is": { "version": "17.0.2", "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", @@ -4025,6 +4056,14 @@ "punycode": "^2.1.0" } }, + "node_modules/use-sync-external-store": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.2.0.tgz", + "integrity": "sha512-eEgnFxGQ1Ife9bzYs6VLi8/4X6CObHMw9Qr9tPY43iKwsPw8xE8+EFsf/2cFZ5S3esXgpWgtSCtLNS41F+sKPA==", + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0" + } + }, "node_modules/utility-types": { "version": "3.10.0", "resolved": "https://registry.npmjs.org/utility-types/-/utility-types-3.10.0.tgz", @@ -4305,6 +4344,29 @@ "funding": { "url": "https://github.com/sponsors/sindresorhus" } + }, + "node_modules/zustand": { + "version": "4.3.8", + "resolved": "https://registry.npmjs.org/zustand/-/zustand-4.3.8.tgz", + "integrity": "sha512-4h28KCkHg5ii/wcFFJ5Fp+k1J3gJoasaIbppdgZFO4BPJnsNxL0mQXBSFgOgAdCdBj35aDTPvdAJReTMntFPGg==", + "dependencies": { + "use-sync-external-store": "1.2.0" + }, + "engines": { + "node": ">=12.7.0" + }, + "peerDependencies": { + "immer": ">=9.0", + "react": ">=16.8" + }, + "peerDependenciesMeta": { + "immer": { + "optional": true + }, + "react": { + "optional": true + } + } } } } diff --git a/styles/package.json b/styles/package.json index d82bbb7e817675ffde132e31922691ba7a117fea..16e95d90d5bebb18e7cfffe88e8d0098b48eb00f 100644 --- a/styles/package.json +++ b/styles/package.json @@ -16,21 +16,22 @@ "@tokens-studio/types": "^0.2.3", "@types/chroma-js": "^2.4.0", "@types/node": "^18.14.1", + "@typescript-eslint/eslint-plugin": "^5.60.1", + "@typescript-eslint/parser": "^5.60.1", + "@vitest/coverage-v8": "^0.32.0", "ayu": "^8.0.1", "chroma-js": "^2.4.2", "deepmerge": "^4.3.0", + "eslint": "^8.43.0", + "eslint-import-resolver-typescript": "^3.5.5", + "eslint-plugin-import": "^2.27.5", "json-schema-to-typescript": "^13.0.2", "toml": "^3.0.0", "ts-deepmerge": "^6.0.3", "ts-node": "^10.9.1", + "typescript": "^5.1.5", "utility-types": "^3.10.0", "vitest": "^0.32.0", - "@typescript-eslint/eslint-plugin": "^5.60.1", - "@typescript-eslint/parser": "^5.60.1", - "@vitest/coverage-v8": "^0.32.0", - "eslint": "^8.43.0", - "eslint-import-resolver-typescript": "^3.5.5", - "eslint-plugin-import": "^2.27.5", - "typescript": "^5.1.5" + "zustand": "^4.3.8" } } diff --git a/styles/src/build_themes.ts b/styles/src/build_themes.ts index 5a091719df2cf1bd115e0570d58fc84b18a66fc4..a9cbad94e7fb104adc35e22c6a0b6943aa44992f 100644 --- a/styles/src/build_themes.ts +++ b/styles/src/build_themes.ts @@ -4,6 +4,7 @@ import * as path from "path" import app from "./style_tree/app" import { ColorScheme, create_color_scheme } from "./theme/color_scheme" import { themes } from "./themes" +import { useThemeStore } from "./theme" const assets_directory = `${__dirname}/../../assets` const temp_directory = fs.mkdtempSync(path.join(tmpdir(), "build-themes")) @@ -20,10 +21,17 @@ function clear_themes(theme_directory: string) { } } +const all_themes: ColorScheme[] = themes.map((theme) => + create_color_scheme(theme) +) + function write_themes(themes: ColorScheme[], output_directory: string) { clear_themes(output_directory) for (const color_scheme of themes) { - const style_tree = app(color_scheme) + const { setTheme } = useThemeStore.getState() + setTheme(color_scheme) + + const style_tree = app() const style_tree_json = JSON.stringify(style_tree, null, 2) const temp_path = path.join(temp_directory, `${color_scheme.name}.json`) const out_path = path.join( @@ -36,8 +44,4 @@ function write_themes(themes: ColorScheme[], output_directory: string) { } } -const all_themes: ColorScheme[] = themes.map((theme) => - create_color_scheme(theme) -) - write_themes(all_themes, `${assets_directory}/themes`) diff --git a/styles/src/build_tokens.ts b/styles/src/build_tokens.ts index e33c3712e64d94d56b9b20d9317c270dd0b0aa28..f51e5eb6cf25caf90052a8a45847fb84ee91a4a2 100644 --- a/styles/src/build_tokens.ts +++ b/styles/src/build_tokens.ts @@ -60,7 +60,7 @@ function write_tokens(themes: ColorScheme[], tokens_directory: string) { for (const theme of themes) { const file_name = slugify(theme.name) + ".json" - const tokens = theme_tokens(theme) + const tokens = theme_tokens() const tokens_json = JSON.stringify(tokens, null, 2) const out_path = path.join(tokens_directory, file_name) fs.writeFileSync(out_path, tokens_json, { mode: 0o644 }) diff --git a/styles/src/component/icon_button.ts b/styles/src/component/icon_button.ts index 79891c2477809a1312c968241ee833b62f0922cd..18b900e83328bf4bd409e30b9579d0296c6b338b 100644 --- a/styles/src/component/icon_button.ts +++ b/styles/src/component/icon_button.ts @@ -1,6 +1,6 @@ import { interactive, toggleable } from "../element" import { background, foreground } from "../style_tree/components" -import { ColorScheme } from "../theme/color_scheme" +import { useTheme, ColorScheme } from "../theme" export type Margin = { top: number @@ -22,10 +22,9 @@ type ToggleableIconButtonOptions = IconButtonOptions & { active_color?: keyof ColorScheme["lowest"] } -export function icon_button( - theme: ColorScheme, - { color, margin, layer }: IconButtonOptions -) { +export function icon_button({ color, margin, layer }: IconButtonOptions) { + const theme = useTheme() + if (!color) color = "base" const m = { @@ -75,8 +74,8 @@ export function toggleable_icon_button( return toggleable({ state: { - inactive: icon_button(theme, { color, margin }), - active: icon_button(theme, { + inactive: icon_button({ color, margin }), + active: icon_button({ color: active_color ? active_color : color, margin, layer: theme.middle, diff --git a/styles/src/component/text_button.ts b/styles/src/component/text_button.ts index 477c2515e320d5e1d4ac2b2cdaf7f8dd587cdde8..50737f976686f4a33b1d4ab5d5a81e61ebefd108 100644 --- a/styles/src/component/text_button.ts +++ b/styles/src/component/text_button.ts @@ -5,7 +5,7 @@ import { foreground, text, } from "../style_tree/components" -import { ColorScheme } from "../theme/color_scheme" +import { useTheme, ColorScheme } from "../theme" import { Margin } from "./icon_button" interface TextButtonOptions { @@ -22,10 +22,13 @@ type ToggleableTextButtonOptions = TextButtonOptions & { active_color?: keyof ColorScheme["lowest"] } -export function text_button( - theme: ColorScheme, - { color, layer, margin, text_properties }: TextButtonOptions -) { +export function text_button({ + color, + layer, + margin, + text_properties, +}: TextButtonOptions) { + const theme = useTheme() if (!color) color = "base" const text_options: TextProperties = { @@ -79,8 +82,8 @@ export function toggleable_text_button( return toggleable({ state: { - inactive: text_button(theme, { color, margin }), - active: text_button(theme, { + inactive: text_button({ color, margin }), + active: text_button({ color: active_color ? active_color : color, margin, layer: theme.middle, diff --git a/styles/src/styleTree/editor.ts b/styles/src/styleTree/editor.ts deleted file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000 diff --git a/styles/src/style_tree/app.ts b/styles/src/style_tree/app.ts index 684614d073b495870b1fc06418623587cc69b768..e4bf232b624ed01f6dd1ddcd20826ab6a43aca1d 100644 --- a/styles/src/style_tree/app.ts +++ b/styles/src/style_tree/app.ts @@ -17,45 +17,47 @@ import terminal from "./terminal" import contact_list from "./contact_list" import toolbar_dropdown_menu from "./toolbar_dropdown_menu" import incoming_call_notification from "./incoming_call_notification" -import { ColorScheme } from "../theme/color_scheme" import welcome from "./welcome" import copilot from "./copilot" import assistant from "./assistant" import { titlebar } from "./titlebar" import editor from "./editor" import feedback from "./feedback" +import { useTheme } from "../common" + +export default function app(): any { + const theme = useTheme() -export default function app(theme: ColorScheme): any { return { meta: { name: theme.name, is_light: theme.is_light, }, - command_palette: command_palette(theme), - contact_notification: contact_notification(theme), - project_shared_notification: project_shared_notification(theme), - incoming_call_notification: incoming_call_notification(theme), - picker: picker(theme), - workspace: workspace(theme), - titlebar: titlebar(theme), - copilot: copilot(theme), - welcome: welcome(theme), - context_menu: context_menu(theme), - editor: editor(theme), - project_diagnostics: project_diagnostics(theme), - project_panel: project_panel(theme), - contacts_popover: contacts_popover(theme), - contact_finder: contact_finder(theme), - contact_list: contact_list(theme), - toolbar_dropdown_menu: toolbar_dropdown_menu(theme), - search: search(theme), - shared_screen: shared_screen(theme), - update_notification: update_notification(theme), - simple_message_notification: simple_message_notification(theme), - tooltip: tooltip(theme), - terminal: terminal(theme), - assistant: assistant(theme), - feedback: feedback(theme), + command_palette: command_palette(), + contact_notification: contact_notification(), + project_shared_notification: project_shared_notification(), + incoming_call_notification: incoming_call_notification(), + picker: picker(), + workspace: workspace(), + titlebar: titlebar(), + copilot: copilot(), + welcome: welcome(), + context_menu: context_menu(), + editor: editor(), + project_diagnostics: project_diagnostics(), + project_panel: project_panel(), + contacts_popover: contacts_popover(), + contact_finder: contact_finder(), + contact_list: contact_list(), + toolbar_dropdown_menu: toolbar_dropdown_menu(), + search: search(), + shared_screen: shared_screen(), + update_notification: update_notification(), + simple_message_notification: simple_message_notification(), + tooltip: tooltip(), + terminal: terminal(), + assistant: assistant(), + feedback: feedback(), color_scheme: { ...theme, players: Object.values(theme.players), diff --git a/styles/src/style_tree/assistant.ts b/styles/src/style_tree/assistant.ts index bdde221acae12f47711f46ea66c5dcc1fbb21d31..6df02a0e330bc24ebc01e7b216be1ed64e20ecd3 100644 --- a/styles/src/style_tree/assistant.ts +++ b/styles/src/style_tree/assistant.ts @@ -1,8 +1,10 @@ -import { ColorScheme } from "../theme/color_scheme" import { text, border, background, foreground } from "./components" import { interactive } from "../element" +import { useTheme } from "../theme" + +export default function assistant(): any { + const theme = useTheme() -export default function assistant(theme: ColorScheme): any { return { container: { background: background(theme.highest), diff --git a/styles/src/style_tree/command_palette.ts b/styles/src/style_tree/command_palette.ts index 289deef54b63b8b71fd24960d88508f7f7d44c98..2f7404c8d4ed2b909e29a4086c7a2339645fea7d 100644 --- a/styles/src/style_tree/command_palette.ts +++ b/styles/src/style_tree/command_palette.ts @@ -1,9 +1,11 @@ -import { ColorScheme } from "../theme/color_scheme" import { with_opacity } from "../theme/color" import { text, background } from "./components" import { toggleable } from "../element" +import { useTheme } from "../theme" + +export default function command_palette(): any { + const theme = useTheme() -export default function command_palette(theme: ColorScheme): any { const key = toggleable({ base: { text: text(theme.highest, "mono", "variant", "default", { diff --git a/styles/src/style_tree/contact_finder.ts b/styles/src/style_tree/contact_finder.ts index e61d100264bb9713f312c27c446ff36f054e77f5..2d57e16dfd5cf9f308b3f3a53d7863f99532507d 100644 --- a/styles/src/style_tree/contact_finder.ts +++ b/styles/src/style_tree/contact_finder.ts @@ -1,8 +1,10 @@ import picker from "./picker" -import { ColorScheme } from "../theme/color_scheme" import { background, border, foreground, text } from "./components" +import { useTheme } from "../theme" + +export default function contact_finder(): any { + const theme = useTheme() -export default function contact_finder(theme: ColorScheme): any { const side_margin = 6 const contact_button = { background: background(theme.middle, "variant"), @@ -12,7 +14,7 @@ export default function contact_finder(theme: ColorScheme): any { corner_radius: 8, } - const picker_style = picker(theme) + const picker_style = picker() const picker_input = { background: background(theme.middle, "on"), corner_radius: 6, diff --git a/styles/src/style_tree/contact_list.ts b/styles/src/style_tree/contact_list.ts index 93f88e2d4afe4df10a943b5d8e04b42d15160e69..1955231f59514847e59248c42f8d301895e38462 100644 --- a/styles/src/style_tree/contact_list.ts +++ b/styles/src/style_tree/contact_list.ts @@ -1,4 +1,3 @@ -import { ColorScheme } from "../theme/color_scheme" import { background, border, @@ -7,7 +6,10 @@ import { text, } from "./components" import { interactive, toggleable } from "../element" -export default function contacts_panel(theme: ColorScheme): any { +import { useTheme } from "../theme" +export default function contacts_panel(): any { + const theme = useTheme() + const name_margin = 8 const side_padding = 12 diff --git a/styles/src/style_tree/contact_notification.ts b/styles/src/style_tree/contact_notification.ts index 8de5496d91e41d054e5f2eee29f08cc7e0c31054..365e3a646ddf71c8f0ba522fe092f9e951d04cd4 100644 --- a/styles/src/style_tree/contact_notification.ts +++ b/styles/src/style_tree/contact_notification.ts @@ -1,8 +1,10 @@ -import { ColorScheme } from "../theme/color_scheme" import { background, foreground, text } from "./components" import { interactive } from "../element" +import { useTheme } from "../theme" + +export default function contact_notification(): any { + const theme = useTheme() -export default function contact_notification(theme: ColorScheme): any { const avatar_size = 12 const header_padding = 8 diff --git a/styles/src/style_tree/contacts_popover.ts b/styles/src/style_tree/contacts_popover.ts index 4e3f8899e046bc27ddcc394c42e845278b73a51d..0ce63d088a72028e6e221cc5739adfe2376d608d 100644 --- a/styles/src/style_tree/contacts_popover.ts +++ b/styles/src/style_tree/contacts_popover.ts @@ -1,7 +1,9 @@ -import { ColorScheme } from "../theme/color_scheme" +import { useTheme } from "../theme" import { background, border } from "./components" -export default function contacts_popover(theme: ColorScheme): any { +export default function contacts_popover(): any { + const theme = useTheme() + return { background: background(theme.middle), corner_radius: 6, diff --git a/styles/src/style_tree/context_menu.ts b/styles/src/style_tree/context_menu.ts index af45942d2d56d69dcb4ca799282d71c203223eec..d4266a71fe6f3974dcf8a154002f658fadf38d07 100644 --- a/styles/src/style_tree/context_menu.ts +++ b/styles/src/style_tree/context_menu.ts @@ -1,8 +1,10 @@ -import { ColorScheme } from "../theme/color_scheme" import { background, border, border_color, text } from "./components" import { interactive, toggleable } from "../element" +import { useTheme } from "../theme" + +export default function context_menu(): any { + const theme = useTheme() -export default function context_menu(theme: ColorScheme): any { return { background: background(theme.middle), corner_radius: 10, diff --git a/styles/src/style_tree/copilot.ts b/styles/src/style_tree/copilot.ts index eee6880e0cfa240ad6b9ce38bc3d7252bf1a427e..f002db5ef586a39abfe3e8698cf4e5ddafb390b3 100644 --- a/styles/src/style_tree/copilot.ts +++ b/styles/src/style_tree/copilot.ts @@ -1,7 +1,9 @@ -import { ColorScheme } from "../theme/color_scheme" import { background, border, foreground, svg, text } from "./components" import { interactive } from "../element" -export default function copilot(theme: ColorScheme): any { +import { useTheme } from "../theme" +export default function copilot(): any { + const theme = useTheme() + const content_width = 264 const cta_button = diff --git a/styles/src/style_tree/editor.ts b/styles/src/style_tree/editor.ts index af58276d162acc741a22079d8cb59b3885e2b6dc..31fa86110da30c5ad56f75291bce674b194fa2fd 100644 --- a/styles/src/style_tree/editor.ts +++ b/styles/src/style_tree/editor.ts @@ -1,5 +1,5 @@ import { with_opacity } from "../theme/color" -import { ColorScheme, Layer, StyleSets } from "../theme/color_scheme" +import { Layer, StyleSets } from "../theme/color_scheme" import { background, border, @@ -11,8 +11,11 @@ import hover_popover from "./hover_popover" import { build_syntax } from "../theme/syntax" import { interactive, toggleable } from "../element" +import { useTheme } from "../theme" + +export default function editor(): any { + const theme = useTheme() -export default function editor(theme: ColorScheme): any { const { is_light } = theme const layer = theme.highest @@ -248,7 +251,7 @@ export default function editor(theme: ColorScheme): any { invalid_hint_diagnostic: diagnostic(theme.middle, "base"), invalid_information_diagnostic: diagnostic(theme.middle, "base"), invalid_warning_diagnostic: diagnostic(theme.middle, "base"), - hover_popover: hover_popover(theme), + hover_popover: hover_popover(), link_definition: { color: syntax.link_uri.color, underline: syntax.link_uri.underline, diff --git a/styles/src/style_tree/feedback.ts b/styles/src/style_tree/feedback.ts index 9217b609299426d5444c9e2703fe843aa98e2350..2bb63e951be4764a6cdb33544abf404a84a11d7e 100644 --- a/styles/src/style_tree/feedback.ts +++ b/styles/src/style_tree/feedback.ts @@ -1,8 +1,10 @@ -import { ColorScheme } from "../theme/color_scheme" import { background, border, text } from "./components" import { interactive } from "../element" +import { useTheme } from "../theme" + +export default function feedback(): any { + const theme = useTheme() -export default function feedback(theme: ColorScheme): any { return { submit_button: interactive({ base: { diff --git a/styles/src/style_tree/hover_popover.ts b/styles/src/style_tree/hover_popover.ts index f4695057419d3adb0af4c8f46413574f6817a479..80f22503496771bf39d8a271c3cfe66988a4b96f 100644 --- a/styles/src/style_tree/hover_popover.ts +++ b/styles/src/style_tree/hover_popover.ts @@ -1,7 +1,9 @@ -import { ColorScheme } from "../theme/color_scheme" +import { useTheme } from "../theme" import { background, border, foreground, text } from "./components" -export default function hover_popover(theme: ColorScheme): any { +export default function hover_popover(): any { + const theme = useTheme() + const base_container = { background: background(theme.middle), corner_radius: 8, diff --git a/styles/src/style_tree/incoming_call_notification.ts b/styles/src/style_tree/incoming_call_notification.ts index ca46596e57fc46ca4fef1baa50d342b41f720c8a..294ec00a73152f4a79f96ba2e0866cc25baf5fa7 100644 --- a/styles/src/style_tree/incoming_call_notification.ts +++ b/styles/src/style_tree/incoming_call_notification.ts @@ -1,9 +1,9 @@ -import { ColorScheme } from "../theme/color_scheme" +import { useTheme } from "../theme" import { background, border, text } from "./components" -export default function incoming_call_notification( - theme: ColorScheme -): unknown { +export default function incoming_call_notification(): unknown { + const theme = useTheme() + const avatar_size = 48 return { window_height: 74, diff --git a/styles/src/style_tree/picker.ts b/styles/src/style_tree/picker.ts index 7ca76cd85f324d9cc640dd3845a1ca1d3e89a751..d57021efb8ca765f196518d8c79727ba4d88513d 100644 --- a/styles/src/style_tree/picker.ts +++ b/styles/src/style_tree/picker.ts @@ -1,9 +1,11 @@ -import { ColorScheme } from "../theme/color_scheme" import { with_opacity } from "../theme/color" import { background, border, text } from "./components" import { interactive, toggleable } from "../element" +import { useTheme } from "../theme" + +export default function picker(): any { + const theme = useTheme() -export default function picker(theme: ColorScheme): any { const container = { background: background(theme.lowest), border: border(theme.lowest), diff --git a/styles/src/style_tree/project_diagnostics.ts b/styles/src/style_tree/project_diagnostics.ts index 5962b98a26ce20ebe2c8c06245cb0d134c3397e9..1c13b31a4af969518d7d06f4668334480a84bdd4 100644 --- a/styles/src/style_tree/project_diagnostics.ts +++ b/styles/src/style_tree/project_diagnostics.ts @@ -1,7 +1,9 @@ -import { ColorScheme } from "../theme/color_scheme" +import { useTheme } from "../theme" import { background, text } from "./components" -export default function project_diagnostics(theme: ColorScheme): any { +export default function project_diagnostics(): any { + const theme = useTheme() + return { background: background(theme.highest), tab_icon_spacing: 4, diff --git a/styles/src/style_tree/project_panel.ts b/styles/src/style_tree/project_panel.ts index d1024778f1d1423eba265ca7a4ee8be7706975cc..af997d0a6e8099a0b8449bf0685df1dd4a0a4eda 100644 --- a/styles/src/style_tree/project_panel.ts +++ b/styles/src/style_tree/project_panel.ts @@ -1,4 +1,3 @@ -import { ColorScheme } from "../theme/color_scheme" import { with_opacity } from "../theme/color" import { Border, @@ -10,7 +9,10 @@ import { } from "./components" import { interactive, toggleable } from "../element" import merge from "ts-deepmerge" -export default function project_panel(theme: ColorScheme): any { +import { useTheme } from "../theme" +export default function project_panel(): any { + const theme = useTheme() + const { is_light } = theme type EntryStateProps = { @@ -65,13 +67,12 @@ export default function project_panel(theme: ColorScheme): any { const unselected_hovered_style = merge( base_properties, { background: background(theme.middle, "hovered") }, - unselected?.hovered ?? {}, + unselected?.hovered ?? {} ) const unselected_clicked_style = merge( base_properties, - { background: background(theme.middle, "pressed"), } - , - unselected?.clicked ?? {}, + { background: background(theme.middle, "pressed") }, + unselected?.clicked ?? {} ) const selected_default_style = merge( base_properties, @@ -79,18 +80,15 @@ export default function project_panel(theme: ColorScheme): any { background: background(theme.lowest), text: text(theme.lowest, "sans", { size: "sm" }), }, - selected_style?.default ?? {}, - + selected_style?.default ?? {} ) const selected_hovered_style = merge( base_properties, { background: background(theme.lowest, "hovered"), text: text(theme.lowest, "sans", { size: "sm" }), - }, - selected_style?.hovered ?? {}, - + selected_style?.hovered ?? {} ) const selected_clicked_style = merge( base_properties, @@ -98,8 +96,7 @@ export default function project_panel(theme: ColorScheme): any { background: background(theme.lowest, "pressed"), text: text(theme.lowest, "sans", { size: "sm" }), }, - selected_style?.clicked ?? {}, - + selected_style?.clicked ?? {} ) return toggleable({ diff --git a/styles/src/style_tree/project_shared_notification.ts b/styles/src/style_tree/project_shared_notification.ts index ffda0f4b70812a9ff1c1ea65ac87a280c8836bad..e7c1dcedd513ecaf07d16464c8510ccd93d36df8 100644 --- a/styles/src/style_tree/project_shared_notification.ts +++ b/styles/src/style_tree/project_shared_notification.ts @@ -1,9 +1,9 @@ -import { ColorScheme } from "../theme/color_scheme" +import { useTheme } from "../theme" import { background, border, text } from "./components" -export default function project_shared_notification( - theme: ColorScheme -): unknown { +export default function project_shared_notification(): unknown { + const theme = useTheme() + const avatar_size = 48 return { window_height: 74, diff --git a/styles/src/style_tree/search.ts b/styles/src/style_tree/search.ts index df260f95b79dc00a22eb3fa23c31b32d03c0007e..5c16d03233ee7af3f22fb3c67bf9b5b4a69f524d 100644 --- a/styles/src/style_tree/search.ts +++ b/styles/src/style_tree/search.ts @@ -1,9 +1,11 @@ -import { ColorScheme } from "../theme/color_scheme" import { with_opacity } from "../theme/color" import { background, border, foreground, text } from "./components" import { interactive, toggleable } from "../element" +import { useTheme } from "../theme" + +export default function search(): any { + const theme = useTheme() -export default function search(theme: ColorScheme): any { // Search input const editor = { background: background(theme.highest), diff --git a/styles/src/style_tree/shared_screen.ts b/styles/src/style_tree/shared_screen.ts index b57c483f1c27b106e44f6a482dc9d8c64cdacacb..aca7fd7f0778d6984cf5d26aea7cab007fad8ebb 100644 --- a/styles/src/style_tree/shared_screen.ts +++ b/styles/src/style_tree/shared_screen.ts @@ -1,7 +1,9 @@ -import { ColorScheme } from "../theme/color_scheme" +import { useTheme } from "../theme" import { background } from "./components" -export default function sharedScreen(theme: ColorScheme) { +export default function sharedScreen() { + const theme = useTheme() + return { background: background(theme.highest), } diff --git a/styles/src/style_tree/simple_message_notification.ts b/styles/src/style_tree/simple_message_notification.ts index 0b5c1e0c294dc9b6f96afb9614a4841b65e2281c..35133f04a2de39cb722b87784f77e08f270fcb78 100644 --- a/styles/src/style_tree/simple_message_notification.ts +++ b/styles/src/style_tree/simple_message_notification.ts @@ -1,8 +1,10 @@ -import { ColorScheme } from "../theme/color_scheme" import { background, border, foreground, text } from "./components" import { interactive } from "../element" +import { useTheme } from "../theme" + +export default function simple_message_notification(): any { + const theme = useTheme() -export default function simple_message_notification(theme: ColorScheme): any { const header_padding = 8 return { diff --git a/styles/src/style_tree/status_bar.ts b/styles/src/style_tree/status_bar.ts index bde40d570c5c2bc8b42af00a52eca9ccb7b8e26b..9aeea866f3b33c738e6630c54ce92b21408cb6f2 100644 --- a/styles/src/style_tree/status_bar.ts +++ b/styles/src/style_tree/status_bar.ts @@ -1,7 +1,9 @@ -import { ColorScheme } from "../theme/color_scheme" import { background, border, foreground, text } from "./components" import { interactive, toggleable } from "../element" -export default function status_bar(theme: ColorScheme): any { +import { useTheme } from "../common" +export default function status_bar(): any { + const theme = useTheme() + const layer = theme.lowest const status_container = { diff --git a/styles/src/style_tree/tab_bar.ts b/styles/src/style_tree/tab_bar.ts index 55fd2c314a9781d4719f5d16fd5cd498202f89a1..29769f9bae27ba5cc69cf81dae95f915051f4bd8 100644 --- a/styles/src/style_tree/tab_bar.ts +++ b/styles/src/style_tree/tab_bar.ts @@ -1,9 +1,11 @@ -import { ColorScheme } from "../theme/color_scheme" import { with_opacity } from "../theme/color" import { text, border, background, foreground } from "./components" import { interactive, toggleable } from "../element" +import { useTheme } from "../common" + +export default function tab_bar(): any { + const theme = useTheme() -export default function tab_bar(theme: ColorScheme): any { const height = 32 const active_layer = theme.highest diff --git a/styles/src/style_tree/terminal.ts b/styles/src/style_tree/terminal.ts index e902aa42647a56b1de3642a0c89673863a62754f..5b98eebfcdb416dfd0acdfd7f15076785eec59b7 100644 --- a/styles/src/style_tree/terminal.ts +++ b/styles/src/style_tree/terminal.ts @@ -1,6 +1,8 @@ -import { ColorScheme } from "../theme/color_scheme" +import { useTheme } from "../theme" + +export default function terminal() { + const theme = useTheme() -export default function terminal(theme: ColorScheme) { /** * Colors are controlled per-cell in the terminal grid. * Cells can be set to any of these more 'theme-capable' colors diff --git a/styles/src/style_tree/titlebar.ts b/styles/src/style_tree/titlebar.ts index 067d619bb524880c1ddd9085a889cf41d3177470..4dbd8f08f9ad014b8de71b9add006478bb8b351d 100644 --- a/styles/src/style_tree/titlebar.ts +++ b/styles/src/style_tree/titlebar.ts @@ -1,7 +1,7 @@ -import { ColorScheme } from "../common" import { icon_button, toggleable_icon_button } from "../component/icon_button" import { toggleable_text_button } from "../component/text_button" import { interactive, toggleable } from "../element" +import { useTheme } from "../theme" import { with_opacity } from "../theme/color" import { background, border, foreground, text } from "./components" @@ -22,7 +22,9 @@ function build_spacing( } } -function call_controls(theme: ColorScheme) { +function call_controls() { + const theme = useTheme() + const button_height = 18 const space = build_spacing(TITLEBAR_HEIGHT, button_height, ITEM_SPACING) @@ -69,7 +71,9 @@ function call_controls(theme: ColorScheme) { * When logged in shows the user's avatar and a chevron, * When logged out only shows a chevron. */ -function user_menu(theme: ColorScheme) { +function user_menu() { + const theme = useTheme() + const button_height = 18 const space = build_spacing(TITLEBAR_HEIGHT, button_height, ITEM_SPACING) @@ -155,7 +159,9 @@ function user_menu(theme: ColorScheme) { } } -export function titlebar(theme: ColorScheme): any { +export function titlebar(): any { + const theme = useTheme() + const avatar_width = 15 const avatar_outer_width = avatar_width + 4 const follower_avatar_width = 14 @@ -237,14 +243,14 @@ export function titlebar(theme: ColorScheme): any { corner_radius: 6, }, - leave_call_button: icon_button(theme, { + leave_call_button: icon_button({ margin: { left: ITEM_SPACING / 2, right: ITEM_SPACING, }, }), - ...call_controls(theme), + ...call_controls(), toggle_contacts_button: toggleable_icon_button(theme, { margin: { @@ -261,6 +267,6 @@ export function titlebar(theme: ColorScheme): any { background: foreground(theme.lowest, "accent"), }, share_button: toggleable_text_button(theme, {}), - user_menu: user_menu(theme), + user_menu: user_menu(), } } diff --git a/styles/src/style_tree/toolbar_dropdown_menu.ts b/styles/src/style_tree/toolbar_dropdown_menu.ts index dc22ac73cf09033a9f446555e871401990b0e81c..97f29ab18c0b873f68b4b020bb2722cadfaa1fbc 100644 --- a/styles/src/style_tree/toolbar_dropdown_menu.ts +++ b/styles/src/style_tree/toolbar_dropdown_menu.ts @@ -1,7 +1,9 @@ -import { ColorScheme } from "../theme/color_scheme" import { background, border, text } from "./components" import { interactive, toggleable } from "../element" -export default function dropdown_menu(theme: ColorScheme): any { +import { useTheme } from "../theme" +export default function dropdown_menu(): any { + const theme = useTheme() + return { row_height: 30, background: background(theme.middle), diff --git a/styles/src/style_tree/tooltip.ts b/styles/src/style_tree/tooltip.ts index 2fa5db04d4f96eee33cca9ea9190dff275ad7e0c..54a2d7b78de071f316ee0151a2f99e7f4198d842 100644 --- a/styles/src/style_tree/tooltip.ts +++ b/styles/src/style_tree/tooltip.ts @@ -1,7 +1,9 @@ -import { ColorScheme } from "../theme/color_scheme" +import { useTheme } from "../theme" import { background, border, text } from "./components" -export default function tooltip(theme: ColorScheme): any { +export default function tooltip(): any { + const theme = useTheme() + return { background: background(theme.middle), border: border(theme.middle), diff --git a/styles/src/style_tree/update_notification.ts b/styles/src/style_tree/update_notification.ts index d14e840450f36a39bc705ac6018563bc1bf4ad81..2d0c36d74cce4514fb48c915f249276c44bc628a 100644 --- a/styles/src/style_tree/update_notification.ts +++ b/styles/src/style_tree/update_notification.ts @@ -1,8 +1,10 @@ -import { ColorScheme } from "../theme/color_scheme" import { foreground, text } from "./components" import { interactive } from "../element" +import { useTheme } from "../theme" + +export default function update_notification(): any { + const theme = useTheme() -export default function update_notification(theme: ColorScheme): any { const header_padding = 8 return { diff --git a/styles/src/style_tree/welcome.ts b/styles/src/style_tree/welcome.ts index fad8dfe23523ba3b1654072251adf3b466963906..8ff15d5d26fd05856747eaa898df9cc052b6f2b7 100644 --- a/styles/src/style_tree/welcome.ts +++ b/styles/src/style_tree/welcome.ts @@ -1,4 +1,3 @@ -import { ColorScheme } from "../theme/color_scheme" import { with_opacity } from "../theme/color" import { border, @@ -9,8 +8,11 @@ import { svg, } from "./components" import { interactive } from "../element" +import { useTheme } from "../theme" + +export default function welcome(): any { + const theme = useTheme() -export default function welcome(theme: ColorScheme): any { const checkbox_base = { corner_radius: 4, padding: { diff --git a/styles/src/style_tree/workspace.ts b/styles/src/style_tree/workspace.ts index 0326de414abea6e189cae93a1321fe0a8c0f4fa0..5aee3c987d34b75d25db5bc9ad69f4d2a0938f7b 100644 --- a/styles/src/style_tree/workspace.ts +++ b/styles/src/style_tree/workspace.ts @@ -1,4 +1,3 @@ -import { ColorScheme } from "../theme/color_scheme" import { with_opacity } from "../theme/color" import { background, @@ -11,9 +10,12 @@ import { import statusBar from "./status_bar" import tabBar from "./tab_bar" import { interactive } from "../element" - import { titlebar } from "./titlebar" -export default function workspace(theme: ColorScheme): any { +import { useTheme } from "../theme" + +export default function workspace(): any { + const theme = useTheme() + const { is_light } = theme return { @@ -85,7 +87,7 @@ export default function workspace(theme: ColorScheme): any { }, leader_border_opacity: 0.7, leader_border_width: 2.0, - tab_bar: tabBar(theme), + tab_bar: tabBar(), modal: { margin: { bottom: 52, @@ -123,8 +125,8 @@ export default function workspace(theme: ColorScheme): any { color: border_color(theme.lowest), width: 1, }, - status_bar: statusBar(theme), - titlebar: titlebar(theme), + status_bar: statusBar(), + titlebar: titlebar(), toolbar: { height: 34, background: background(theme.highest), diff --git a/styles/src/theme/index.ts b/styles/src/theme/index.ts index 22287bf6699a7f690b1b6b29b0689adc47dea757..100248b1a8df5fc1edfb0a1b92a7ecde27c7bae0 100644 --- a/styles/src/theme/index.ts +++ b/styles/src/theme/index.ts @@ -1,3 +1,24 @@ +import { create } from "zustand" +import { ColorScheme } from "./color_scheme" + +type ThemeState = { + theme: ColorScheme | undefined + setTheme: (theme: ColorScheme) => void +} + +export const useThemeStore = create((set) => ({ + theme: undefined, + setTheme: (theme) => set(() => ({ theme })), +})) + +export const useTheme = (): ColorScheme => { + const { theme } = useThemeStore.getState() + + if (!theme) throw new Error("Tried to use theme before it was loaded") + + return theme +} + export * from "./color_scheme" export * from "./ramps" export * from "./syntax" diff --git a/styles/src/theme/tokens/color_scheme.ts b/styles/src/theme/tokens/color_scheme.ts index a8ce4ec2d252de5f8ec13963c5f41ecbb8ab3424..efbeaaa901eb110964d180f1e92a349c47624efd 100644 --- a/styles/src/theme/tokens/color_scheme.ts +++ b/styles/src/theme/tokens/color_scheme.ts @@ -15,6 +15,7 @@ import { PlayersToken, players_token } from "./players" import { color_token } from "./token" import { Syntax } from "../syntax" import editor from "../../style_tree/editor" +import { useTheme } from "@/src/common" interface ColorSchemeTokens { name: SingleOtherToken @@ -39,12 +40,14 @@ const create_shadow_token = ( } } -const popover_shadow_token = (theme: ColorScheme): SingleBoxShadowToken => { +const popover_shadow_token = (): SingleBoxShadowToken => { + const theme = useTheme() const shadow = theme.popover_shadow return create_shadow_token(shadow, "popover_shadow") } -const modal_shadow_token = (theme: ColorScheme): SingleBoxShadowToken => { +const modal_shadow_token = (): SingleBoxShadowToken => { + const theme = useTheme() const shadow = theme.modal_shadow return create_shadow_token(shadow, "modal_shadow") } @@ -68,13 +71,15 @@ function syntax_highlight_style_color_tokens( }, {} as ThemeSyntaxColorTokens) } -const syntax_tokens = (theme: ColorScheme): ColorSchemeTokens["syntax"] => { - const syntax = editor(theme).syntax +const syntax_tokens = (): ColorSchemeTokens["syntax"] => { + const syntax = editor().syntax return syntax_highlight_style_color_tokens(syntax) } -export function theme_tokens(theme: ColorScheme): ColorSchemeTokens { +export function theme_tokens(): ColorSchemeTokens { + const theme = useTheme() + return { name: { name: "themeName", @@ -89,9 +94,9 @@ export function theme_tokens(theme: ColorScheme): ColorSchemeTokens { lowest: layer_token(theme.lowest, "lowest"), middle: layer_token(theme.middle, "middle"), highest: layer_token(theme.highest, "highest"), - popover_shadow: popover_shadow_token(theme), - modal_shadow: modal_shadow_token(theme), - players: players_token(theme), - syntax: syntax_tokens(theme), + popover_shadow: popover_shadow_token(), + modal_shadow: modal_shadow_token(), + players: players_token(), + syntax: syntax_tokens(), } } diff --git a/styles/src/theme/tokens/players.ts b/styles/src/theme/tokens/players.ts index 545a712ff123e12aaa2dd32a9645ea64001dd061..85573a1a8f6c4031de681e5d9a43f2d4893dac2b 100644 --- a/styles/src/theme/tokens/players.ts +++ b/styles/src/theme/tokens/players.ts @@ -1,12 +1,14 @@ import { SingleColorToken } from "@tokens-studio/types" import { color_token } from "./token" -import { ColorScheme, Players } from "../color_scheme" +import { Players } from "../color_scheme" +import { useTheme } from "@/src/common" export type PlayerToken = Record<"selection" | "cursor", SingleColorToken> export type PlayersToken = Record -function build_player_token(theme: ColorScheme, index: number): PlayerToken { +function build_player_token(index: number): PlayerToken { + const theme = useTheme() const player_number = index.toString() as keyof Players return { @@ -21,13 +23,15 @@ function build_player_token(theme: ColorScheme, index: number): PlayerToken { } } -export const players_token = (theme: ColorScheme): PlayersToken => ({ - "0": build_player_token(theme, 0), - "1": build_player_token(theme, 1), - "2": build_player_token(theme, 2), - "3": build_player_token(theme, 3), - "4": build_player_token(theme, 4), - "5": build_player_token(theme, 5), - "6": build_player_token(theme, 6), - "7": build_player_token(theme, 7), -}) +export const players_token = (): PlayersToken => { + return { + "0": build_player_token(0), + "1": build_player_token(1), + "2": build_player_token(2), + "3": build_player_token(3), + "4": build_player_token(4), + "5": build_player_token(5), + "6": build_player_token(6), + "7": build_player_token(7), + } +}