diff --git a/styles/package-lock.json b/styles/package-lock.json index 3f73a0b4e5..6fc5f746e5 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 d82bbb7e81..16e95d90d5 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 5a091719df..a9cbad94e7 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/component/icon_button.ts b/styles/src/component/icon_button.ts index 79891c2477..18b900e833 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 477c2515e3..50737f9766 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 e69de29bb2..0000000000 diff --git a/styles/src/style_tree/app.ts b/styles/src/style_tree/app.ts index 684614d073..e4bf232b62 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 bdde221aca..6df02a0e33 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 289deef54b..2f7404c8d4 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 e61d100264..2d57e16dfd 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 93f88e2d4a..1955231f59 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 8de5496d91..365e3a646d 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 4e3f8899e0..0ce63d088a 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 af45942d2d..d4266a71fe 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 eee6880e0c..f002db5ef5 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 af58276d16..31fa86110d 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 9217b60929..2bb63e951b 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 f469505741..80f2250349 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 ca46596e57..294ec00a73 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 7ca76cd85f..d57021efb8 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 5962b98a26..1c13b31a4a 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 d1024778f1..af997d0a6e 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 ffda0f4b70..e7c1dcedd5 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 df260f95b7..5c16d03233 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 b57c483f1c..aca7fd7f07 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 0b5c1e0c29..35133f04a2 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 bde40d570c..9aeea866f3 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 55fd2c314a..29769f9bae 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 e902aa4264..5b98eebfcd 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 067d619bb5..4dbd8f08f9 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 dc22ac73cf..97f29ab18c 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 2fa5db04d4..54a2d7b78d 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 d14e840450..2d0c36d74c 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 fad8dfe235..8ff15d5d26 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 0326de414a..5aee3c987d 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 22287bf669..100248b1a8 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"