From 9f19d8fb4bd22518879343b49c05634dca777df0 Mon Sep 17 00:00:00 2001 From: filtered <176114999+webfiltered@users.noreply.github.com> Date: Sat, 27 Sep 2025 05:01:53 +1000 Subject: [PATCH] Migrate Tailwind styles to design-system package (#5794) ## Summary Consolidates Tailwind configuration and styles into a shared `@comfyorg/design-system` package for reuse across monorepo apps. The goal was not to make changes to how the design system works; merely to separate it cleanly. I _would_ strongly recommend some drastic sweeping changes, however I believe that should be done after the migration. ## Changes - **What**: Migrates CSS files, Tailwind config, and custom icons to design-system package - **Dependencies**: Moves `@iconify-json/lucide` and `@iconify/tailwind` to design-system package --- .storybook/main.ts | 2 +- CONTRIBUTING.md | 4 +- package.json | 3 +- packages/design-system/package.json | 31 + .../design-system/src}/css/fonts.css | 0 packages/design-system/src/css/style.css | 1003 ++++++++++++++++ .../design-system/src/iconCollection.ts | 2 +- .../design-system/src}/icons/README.md | 12 +- .../design-system/src/icons}/ai-model.svg | 0 .../design-system/src/icons}/mask.svg | 0 .../design-system/src/icons}/node.svg | 0 .../design-system/src/icons}/template.svg | 0 .../design-system/src/icons}/workflow.svg | 0 packages/design-system/tailwind.config.ts | 26 + packages/design-system/tsconfig.json | 8 + pnpm-lock.yaml | 238 +++- src/assets/css/style.css | 1007 +---------------- tailwind.config.ts | 28 +- tsconfig.json | 1 + vite.config.mts | 2 +- vitest.config.ts | 2 +- 21 files changed, 1318 insertions(+), 1051 deletions(-) create mode 100644 packages/design-system/package.json rename {src/assets => packages/design-system/src}/css/fonts.css (100%) create mode 100644 packages/design-system/src/css/style.css rename build/customIconCollection.ts => packages/design-system/src/iconCollection.ts (96%) rename {src/assets => packages/design-system/src}/icons/README.md (95%) rename {src/assets/icons/custom => packages/design-system/src/icons}/ai-model.svg (100%) rename {src/assets/icons/custom => packages/design-system/src/icons}/mask.svg (100%) rename {src/assets/icons/custom => packages/design-system/src/icons}/node.svg (100%) rename {src/assets/icons/custom => packages/design-system/src/icons}/template.svg (100%) rename {src/assets/icons/custom => packages/design-system/src/icons}/workflow.svg (100%) create mode 100644 packages/design-system/tailwind.config.ts create mode 100644 packages/design-system/tsconfig.json diff --git a/.storybook/main.ts b/.storybook/main.ts index aa6bb1fbd..e8021974b 100644 --- a/.storybook/main.ts +++ b/.storybook/main.ts @@ -45,7 +45,7 @@ const config: StorybookConfig = { compiler: 'vue3', customCollections: { comfy: FileSystemIconLoader( - process.cwd() + '/src/assets/icons/custom' + process.cwd() + '/packages/design-system/src/icons' ) } }), diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 6f4fd8db8..6614fe619 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -265,9 +265,9 @@ The project supports three types of icons, all with automatic imports (no manual 2. **Iconify Icons** - 200,000+ icons from various libraries: ``, `` 3. **Custom Icons** - Your own SVG icons: `` -Icons are powered by the unplugin-icons system, which automatically discovers and imports icons as Vue components. Custom icons are stored in `src/assets/icons/custom/` and processed by `build/customIconCollection.ts` with automatic validation. +Icons are powered by the unplugin-icons system, which automatically discovers and imports icons as Vue components. Custom icons are stored in `packages/design-system/src/icons/` and processed by `packages/design-system/src/iconCollection.ts` with automatic validation. -For detailed instructions and code examples, see [src/assets/icons/README.md](src/assets/icons/README.md). +For detailed instructions and code examples, see [packages/design-system/src/icons/README.md](packages/design-system/src/icons/README.md). ## Working with litegraph.js diff --git a/package.json b/package.json index 70f728756..75a7349ab 100644 --- a/package.json +++ b/package.json @@ -42,8 +42,6 @@ }, "devDependencies": { "@eslint/js": "^9.35.0", - "@iconify-json/lucide": "^1.2.66", - "@iconify/tailwind": "^1.2.0", "@intlify/eslint-plugin-vue-i18n": "^4.1.0", "@lobehub/i18n-cli": "^1.25.1", "@nx/eslint": "21.4.1", @@ -107,6 +105,7 @@ "@alloc/quick-lru": "^5.2.0", "@atlaskit/pragmatic-drag-and-drop": "^1.3.1", "@comfyorg/comfyui-electron-types": "0.4.73-0", + "@comfyorg/design-system": "workspace:*", "@comfyorg/tailwind-utils": "workspace:*", "@iconify/json": "^2.2.380", "@primeuix/forms": "0.0.2", diff --git a/packages/design-system/package.json b/packages/design-system/package.json new file mode 100644 index 000000000..e2868d054 --- /dev/null +++ b/packages/design-system/package.json @@ -0,0 +1,31 @@ +{ + "name": "@comfyorg/design-system", + "version": "1.0.0", + "description": "Shared design system for ComfyUI Frontend", + "type": "module", + "exports": { + "./tailwind-config": { + "import": "./tailwind.config.ts", + "types": "./tailwind.config.ts" + }, + "./css/*": "./src/css/*" + }, + "scripts": { + "typecheck": "tsc --noEmit" + }, + "nx": { + "tags": [ + "scope:shared", + "type:design" + ] + }, + "dependencies": { + "@iconify-json/lucide": "^1.1.178", + "@iconify/tailwind": "^1.1.3" + }, + "devDependencies": { + "tailwindcss": "^3.4.17", + "typescript": "^5.4.5" + }, + "packageManager": "pnpm@10.17.1" +} diff --git a/src/assets/css/fonts.css b/packages/design-system/src/css/fonts.css similarity index 100% rename from src/assets/css/fonts.css rename to packages/design-system/src/css/fonts.css diff --git a/packages/design-system/src/css/style.css b/packages/design-system/src/css/style.css new file mode 100644 index 000000000..0f2bca812 --- /dev/null +++ b/packages/design-system/src/css/style.css @@ -0,0 +1,1003 @@ +@layer theme, base, primevue, components, utilities; + +@import './fonts.css'; +@import 'tailwindcss/theme' layer(theme); +@import 'tailwindcss/utilities' layer(utilities); +@import 'tw-animate-css'; + +@plugin 'tailwindcss-primeui'; + +@config '../../tailwind.config.ts'; + +:root { + --fg-color: #000; + --bg-color: #fff; + --comfy-menu-bg: #353535; + --comfy-menu-secondary-bg: #292929; + --comfy-topbar-height: 2.5rem; + --comfy-input-bg: #222; + --input-text: #ddd; + --descrip-text: #999; + --drag-text: #ccc; + --error-text: #ff4444; + --border-color: #4e4e4e; + --tr-even-bg-color: #222; + --tr-odd-bg-color: #353535; + --primary-bg: #236692; + --primary-fg: #ffffff; + --primary-hover-bg: #3485bb; + --primary-hover-fg: #ffffff; + --content-bg: #e0e0e0; + --content-fg: #000; + --content-hover-bg: #adadad; + --content-hover-fg: #000; + + /* Code styling colors for help menu*/ + --code-text-color: rgba(0, 122, 255, 1); + --code-bg-color: rgba(96, 165, 250, 0.2); + --code-block-bg-color: rgba(60, 60, 60, 0.12); +} + +@media (prefers-color-scheme: dark) { + :root { + --fg-color: #fff; + --bg-color: #202020; + --content-bg: #4e4e4e; + --content-fg: #fff; + --content-hover-bg: #222; + --content-hover-fg: #fff; + } +} + +@theme { + --text-xxs: 0.625rem; + --text-xxs--line-height: calc(1 / 0.625); + + /* Font Families */ + --font-inter: 'Inter', sans-serif; + + /* Palette Colors */ + --color-charcoal-100: #55565e; + --color-charcoal-200: #494a50; + --color-charcoal-300: #3c3d42; + --color-charcoal-400: #313235; + --color-charcoal-500: #2d2e32; + --color-charcoal-600: #262729; + --color-charcoal-700: #202121; + --color-charcoal-800: #171718; + + --color-neutral-550: #636363; + + --color-stone-100: #444444; + --color-stone-200: #828282; + --color-stone-300: #bbbbbb; + + --color-ivory-100: #fdfbfa; + --color-ivory-200: #faf9f5; + --color-ivory-300: #f0eee6; + + --color-gray-100: #f3f3f3; + --color-gray-200: #e9e9e9; + --color-gray-300: #e1e1e1; + --color-gray-400: #d9d9d9; + --color-gray-500: #c5c5c5; + --color-gray-600: #b4b4b4; + --color-gray-700: #a0a0a0; + --color-gray-800: #8a8a8a; + + --color-sand-100: #e1ded5; + --color-sand-200: #d6cfc2; + --color-sand-300: #888682; + + --color-pure-white: #ffffff; + + --color-slate-100: #9c9eab; + --color-slate-200: #9fa2bd; + --color-slate-300: #5b5e7d; + + --color-brand-yellow: #f0ff41; + --color-brand-blue: #172dd7; + + --color-blue-100: #0b8ce9; + --color-blue-200: #31b9f4; + --color-success-100: #00cd72; + --color-success-200: #47e469; + --color-warning-100: #fd9903; + --color-warning-200: #fcbf64; + --color-danger-100: #c02323; + --color-danger-200: #d62952; + + --color-coral-red-600: #973a40; + --color-coral-red-500: #c53f49; + --color-coral-red-400: #dd424e; + + --color-bypass: #6a246a; + --color-error: #962a2a; + + --color-blue-selection: rgb(from var(--color-blue-100) r g b / 0.3); + --color-node-hover-100: rgb(from var(--color-charcoal-100) r g b/ 0.15); + --color-node-hover-200: rgb(from var(--color-charcoal-100) r g b/ 0.1); + --color-modal-tag: rgb(from var(--color-gray-400) r g b/ 0.4); + + /* PrimeVue pulled colors */ + --color-muted: var(--p-text-muted-color); + --color-highlight: var(--p-primary-color); + + /* Special Colors (temporary) */ + --color-dark-elevation-1.5: rgba(from white r g b/ 0.015); + --color-dark-elevation-2: rgba(from white r g b / 0.03); +} + +@theme inline { + --color-node-component-surface: var(--color-charcoal-600); + --color-node-component-surface-highlight: var(--color-slate-100); + --color-node-component-surface-hovered: var(--color-charcoal-400); + --color-node-component-surface-selected: var(--color-charcoal-200); + --color-node-stroke: var(--color-stone-100); +} + +@custom-variant dark-theme { + .dark-theme & { + @slot; + } +} + +@utility scrollbar-hide { + scrollbar-width: none; + &::-webkit-scrollbar { + width: 1px; + } + &::-webkit-scrollbar-thumb { + background-color: transparent; + } +} + +/* Everthing below here to be cleaned up over time. */ + +body { + width: 100vw; + height: 100vh; + margin: 0; + overflow: hidden; + background: var(--bg-color) var(--bg-img); + color: var(--fg-color); + min-height: -webkit-fill-available; + max-height: -webkit-fill-available; + min-width: -webkit-fill-available; + max-width: -webkit-fill-available; + font-family: Arial, sans-serif; +} + +.comfy-multiline-input { + background-color: var(--comfy-input-bg); + color: var(--input-text); + overflow: hidden; + overflow-y: auto; + padding: 2px; + resize: none; + border: none; + box-sizing: border-box; + font-size: var(--comfy-textarea-font-size); +} + +.comfy-markdown { + /* We assign the textarea and the Tiptap editor to the same CSS grid area to stack them on top of one another. */ + display: grid; +} + +.comfy-markdown > textarea { + grid-area: 1 / 1 / 2 / 2; +} + +.comfy-markdown .tiptap { + grid-area: 1 / 1 / 2 / 2; + background-color: var(--comfy-input-bg); + color: var(--input-text); + overflow: hidden; + overflow-y: auto; + resize: none; + border: none; + box-sizing: border-box; + font-size: var(--comfy-textarea-font-size); + height: 100%; + padding: 0.5em; +} + +.comfy-markdown.editing .tiptap { + display: none; +} + +.comfy-markdown .tiptap :first-child { + margin-top: 0; +} + +.comfy-markdown .tiptap :last-child { + margin-bottom: 0; +} + +.comfy-markdown .tiptap blockquote { + border-left: medium solid; + margin-left: 1em; + padding-left: 0.5em; +} + +.comfy-markdown .tiptap pre { + border: thin dotted; + border-radius: 0.5em; + margin: 0.5em; + padding: 0.5em; +} + +.comfy-markdown .tiptap table { + border-collapse: collapse; +} + +.comfy-markdown .tiptap th { + text-align: left; + background: var(--comfy-menu-bg); +} + +.comfy-markdown .tiptap th, +.comfy-markdown .tiptap td { + padding: 0.5em; + border: thin solid; +} + +/* Shared markdown content styling for consistent rendering across components */ +.comfy-markdown-content { + /* Typography */ + font-size: 0.875rem; /* text-sm */ + line-height: 1.6; + word-wrap: break-word; +} + +/* Headings */ +.comfy-markdown-content h1 { + font-size: 22px; /* text-[22px] */ + font-weight: 700; /* font-bold */ + margin-top: 2rem; /* mt-8 */ + margin-bottom: 1rem; /* mb-4 */ +} + +.comfy-markdown-content h1:first-child { + margin-top: 0; /* first:mt-0 */ +} + +.comfy-markdown-content h2 { + font-size: 18px; /* text-[18px] */ + font-weight: 700; /* font-bold */ + margin-top: 2rem; /* mt-8 */ + margin-bottom: 1rem; /* mb-4 */ +} + +.comfy-markdown-content h2:first-child { + margin-top: 0; /* first:mt-0 */ +} + +.comfy-markdown-content h3 { + font-size: 16px; /* text-[16px] */ + font-weight: 700; /* font-bold */ + margin-top: 2rem; /* mt-8 */ + margin-bottom: 1rem; /* mb-4 */ +} + +.comfy-markdown-content h3:first-child { + margin-top: 0; /* first:mt-0 */ +} + +.comfy-markdown-content h4, +.comfy-markdown-content h5, +.comfy-markdown-content h6 { + margin-top: 2rem; /* mt-8 */ + margin-bottom: 1rem; /* mb-4 */ +} + +.comfy-markdown-content h4:first-child, +.comfy-markdown-content h5:first-child, +.comfy-markdown-content h6:first-child { + margin-top: 0; /* first:mt-0 */ +} + +/* Paragraphs */ +.comfy-markdown-content p { + margin: 0 0 0.5em; +} + +.comfy-markdown-content p:last-child { + margin-bottom: 0; +} + +/* First child reset */ +.comfy-markdown-content *:first-child { + margin-top: 0; /* mt-0 */ +} + +/* Lists */ +.comfy-markdown-content ul, +.comfy-markdown-content ol { + padding-left: 2rem; /* pl-8 */ + margin: 0.5rem 0; /* my-2 */ +} + +/* Nested lists */ +.comfy-markdown-content ul ul, +.comfy-markdown-content ol ol, +.comfy-markdown-content ul ol, +.comfy-markdown-content ol ul { + padding-left: 1.5rem; /* pl-6 */ + margin: 0.5rem 0; /* my-2 */ +} + +.comfy-markdown-content li { + margin: 0.5rem 0; /* my-2 */ +} + +/* Code */ +.comfy-markdown-content code { + color: var(--code-text-color); + background-color: var(--code-bg-color); + border-radius: 0.25rem; /* rounded */ + padding: 0.125rem 0.375rem; /* px-1.5 py-0.5 */ + font-family: monospace; +} + +.comfy-markdown-content pre { + background-color: var(--code-block-bg-color); + border-radius: 0.25rem; /* rounded */ + padding: 1rem; /* p-4 */ + margin: 1rem 0; /* my-4 */ + overflow-x: auto; /* overflow-x-auto */ +} + +.comfy-markdown-content pre code { + background-color: transparent; /* bg-transparent */ + padding: 0; /* p-0 */ + color: var(--p-text-color); +} + +/* Tables */ +.comfy-markdown-content table { + width: 100%; /* w-full */ + border-collapse: collapse; /* border-collapse */ +} + +.comfy-markdown-content th, +.comfy-markdown-content td { + padding: 0.5rem; /* px-2 py-2 */ +} + +.comfy-markdown-content th { + color: var(--fg-color); +} + +.comfy-markdown-content td { + color: var(--drag-text); +} + +.comfy-markdown-content tr { + border-bottom: 1px solid var(--content-bg); +} + +.comfy-markdown-content tr:last-child { + border-bottom: none; +} + +.comfy-markdown-content thead { + border-bottom: 1px solid var(--p-text-color); +} + +/* Links */ +.comfy-markdown-content a { + color: var(--drag-text); + text-decoration: underline; +} + +/* Media */ +.comfy-markdown-content img, +.comfy-markdown-content video { + max-width: 100%; /* max-w-full */ + height: auto; /* h-auto */ + display: block; /* block */ + margin-bottom: 1rem; /* mb-4 */ +} + +/* Blockquotes */ +.comfy-markdown-content blockquote { + border-left: 3px solid var(--p-primary-color, var(--primary-bg)); + padding-left: 0.75em; + margin: 0.5em 0; + opacity: 0.8; +} + +/* Horizontal rule */ +.comfy-markdown-content hr { + border: none; + border-top: 1px solid var(--p-border-color, var(--border-color)); + margin: 1em 0; +} + +/* Strong and emphasis */ +.comfy-markdown-content strong { + font-weight: bold; +} + +.comfy-markdown-content em { + font-style: italic; +} + +.comfy-modal { + display: none; /* Hidden by default */ + position: fixed; /* Stay in place */ + z-index: 100; /* Sit on top */ + padding: 30px 30px 10px 30px; + background-color: var(--comfy-menu-bg); /* Modal background */ + color: var(--error-text); + box-shadow: 0 0 20px #888888; + border-radius: 10px; + top: 50%; + left: 50%; + max-width: 80vw; + max-height: 80vh; + transform: translate(-50%, -50%); + overflow: hidden; + justify-content: center; + font-family: monospace; + font-size: 15px; +} + +.comfy-modal-content { + display: flex; + flex-direction: column; +} + +.comfy-modal p { + overflow: auto; + white-space: pre-line; /* This will respect line breaks */ + margin-bottom: 20px; /* Add some margin between the text and the close button*/ +} + +.comfy-modal select, +.comfy-modal input[type='button'], +.comfy-modal input[type='checkbox'] { + margin: 3px 3px 3px 4px; +} + +.comfy-menu { + font-size: 15px; + position: absolute; + top: 50%; + right: 0; + text-align: center; + z-index: 999; + width: 190px; + display: flex; + flex-direction: column; + align-items: center; + color: var(--descrip-text); + background-color: var(--comfy-menu-bg); + font-family: sans-serif; + padding: 10px; + border-radius: 0 8px 8px 8px; + box-shadow: 3px 3px 8px rgba(0, 0, 0, 0.4); +} + +.comfy-menu-header { + display: flex; +} + +.comfy-menu-actions { + display: flex; + gap: 3px; + align-items: center; + height: 20px; + position: relative; + top: -1px; + font-size: 22px; +} + +.comfy-menu .comfy-menu-actions button { + background-color: rgba(0, 0, 0, 0); + padding: 0; + border: none; + cursor: pointer; + font-size: inherit; +} + +.comfy-menu .comfy-menu-actions .comfy-settings-btn { + font-size: 0.6em; +} + +button.comfy-close-menu-btn { + font-size: 1em; + line-height: 12px; + color: #ccc; + position: relative; + top: -1px; +} + +.comfy-menu-queue-size { + flex: auto; +} + +.comfy-menu button, +.comfy-modal button { + font-size: 20px; +} + +.comfy-menu-btns { + margin-bottom: 10px; + width: 100%; +} + +.comfy-menu-btns button { + font-size: 10px; + width: 50%; + color: var(--descrip-text) !important; +} + +.comfy-menu > button { + width: 100%; +} + +.comfy-btn, +.comfy-menu > button, +.comfy-menu-btns button, +.comfy-menu .comfy-list button, +.comfy-modal button { + color: var(--input-text); + background-color: var(--comfy-input-bg); + border-width: initial; + border-radius: 8px; + border-color: var(--border-color); + border-style: solid; + margin-top: 2px; +} + +.comfy-btn:hover:not(:disabled), +.comfy-menu > button:hover, +.comfy-menu-btns button:hover, +.comfy-menu .comfy-list button:hover, +.comfy-modal button:hover, +.comfy-menu-actions button:hover { + filter: brightness(1.2); + will-change: transform; + cursor: pointer; +} + +span.drag-handle { + width: 10px; + height: 20px; + display: inline-block; + overflow: hidden; + line-height: 5px; + padding: 3px 4px; + cursor: move; + vertical-align: middle; + margin-top: -0.4em; + margin-left: -0.2em; + font-size: 12px; + font-family: sans-serif; + letter-spacing: 2px; + color: var(--drag-text); + text-shadow: 1px 0 1px black; + touch-action: none; +} + +span.drag-handle::after { + content: '.. .. ..'; +} + +.comfy-queue-btn { + width: 100%; +} + +.comfy-list { + color: var(--descrip-text); + background-color: var(--comfy-menu-bg); + margin-bottom: 10px; + border-color: var(--border-color); + border-style: solid; +} + +.comfy-list-items { + overflow-y: scroll; + max-height: 100px; + min-height: 25px; + background-color: var(--comfy-input-bg); + padding: 5px; +} + +.comfy-list h4 { + min-width: 160px; + margin: 0; + padding: 3px; + font-weight: normal; +} + +.comfy-list-items button { + font-size: 10px; +} + +.comfy-list-actions { + margin: 5px; + display: flex; + gap: 5px; + justify-content: center; +} + +.comfy-list-actions button { + font-size: 12px; +} + +button.comfy-queue-btn { + margin: 6px 0 !important; +} + +.comfy-modal.comfy-settings, +.comfy-modal.comfy-manage-templates { + text-align: center; + font-family: sans-serif; + color: var(--descrip-text); + z-index: 99; +} + +.comfy-modal.comfy-settings input[type='range'] { + vertical-align: middle; +} + +.comfy-modal.comfy-settings input[type='range'] + input[type='number'] { + width: 3.5em; +} + +.comfy-modal input, +.comfy-modal select { + color: var(--input-text); + background-color: var(--comfy-input-bg); + border-radius: 8px; + border-color: var(--border-color); + border-style: solid; + font-size: inherit; +} + +.comfy-tooltip-indicator { + text-decoration: underline; + text-decoration-style: dashed; +} + +@media only screen and (max-height: 850px) { + .comfy-menu { + top: 0 !important; + bottom: 0 !important; + left: auto !important; + right: 0 !important; + border-radius: 0; + } + + .comfy-menu span.drag-handle { + display: none; + } + + .comfy-menu-queue-size { + flex: unset; + } + + .comfy-menu-header { + justify-content: space-between; + } + .comfy-menu-actions { + gap: 10px; + font-size: 28px; + } +} + +/* Input popup */ + +.graphdialog { + min-height: 1em; + background-color: var(--comfy-menu-bg); + z-index: 41; /* z-index is set to 41 here in order to appear over selection-overlay-container which should have a z-index of 40 */ +} + +.graphdialog .name { + font-size: 14px; + font-family: sans-serif; + color: var(--descrip-text); +} + +.graphdialog button { + margin-top: unset; + vertical-align: unset; + height: 1.6em; + padding-right: 8px; +} + +.graphdialog input, +.graphdialog textarea, +.graphdialog select { + background-color: var(--comfy-input-bg); + border: 2px solid; + border-color: var(--border-color); + color: var(--input-text); + border-radius: 12px 0 0 12px; +} + +/* Dialogs */ + +dialog { + box-shadow: 0 0 20px #888888; +} + +dialog::backdrop { + background: rgba(0, 0, 0, 0.5); +} + +.comfy-dialog.comfyui-dialog.comfy-modal { + top: 0; + left: 0; + right: 0; + bottom: 0; + transform: none; +} + +.comfy-dialog.comfy-modal { + font-family: Arial, sans-serif; + border-color: var(--bg-color); + box-shadow: none; + border: 2px solid var(--border-color); +} + +.comfy-dialog .comfy-modal-content { + flex-direction: row; + flex-wrap: wrap; + gap: 10px; + color: var(--fg-color); +} + +.comfy-dialog .comfy-modal-content h3 { + margin-top: 0; +} + +.comfy-dialog .comfy-modal-content > p { + width: 100%; +} + +.comfy-dialog .comfy-modal-content > .comfyui-button { + flex: 1; + justify-content: center; +} + +/* Context menu */ + +.litegraph .dialog { + z-index: 1; + font-family: Arial, sans-serif; +} + +.litegraph .litemenu-entry.has_submenu { + position: relative; + padding-right: 20px; +} + +.litemenu-entry.has_submenu::after { + content: '>'; + position: absolute; + top: 0; + right: 2px; +} + +.litegraph.litecontextmenu, +.litegraph.litecontextmenu.dark { + z-index: 9999 !important; + background-color: var(--comfy-menu-bg) !important; +} + +.litegraph.litecontextmenu + .litemenu-entry:hover:not(.disabled):not(.separator) { + background-color: var(--comfy-menu-hover-bg, var(--border-color)) !important; + color: var(--fg-color); +} + +.litegraph.litecontextmenu .litemenu-entry.submenu, +.litegraph.litecontextmenu.dark .litemenu-entry.submenu { + background-color: var(--comfy-menu-bg) !important; + color: var(--input-text); +} + +.litegraph.litecontextmenu input { + background-color: var(--comfy-input-bg) !important; + color: var(--input-text) !important; +} + +.comfy-context-menu-filter { + box-sizing: border-box; + border: 1px solid #999; + margin: 0 0 5px 5px; + width: calc(100% - 10px); +} + +.comfy-img-preview { + pointer-events: none; + overflow: hidden; + display: flex; + flex-wrap: wrap; + align-content: flex-start; + justify-content: center; +} + +.comfy-img-preview img { + object-fit: contain; + width: var(--comfy-img-preview-width); + height: var(--comfy-img-preview-height); +} + +.comfy-img-preview video { + pointer-events: auto; + object-fit: contain; + height: 100%; + width: 100%; +} + +.comfy-missing-nodes li button { + font-size: 12px; + margin-left: 5px; +} + +/* Search box */ + +.litegraph.litesearchbox { + z-index: 9999 !important; + background-color: var(--comfy-menu-bg) !important; + overflow: hidden; + display: block; +} + +.litegraph.litesearchbox input, +.litegraph.litesearchbox select { + background-color: var(--comfy-input-bg) !important; + color: var(--input-text); +} + +.litegraph.lite-search-item { + color: var(--input-text); + background-color: var(--comfy-input-bg); + filter: brightness(80%); + will-change: transform; + padding-left: 0.2em; +} + +.litegraph.lite-search-item.generic_type { + color: var(--input-text); + filter: brightness(50%); + will-change: transform; +} + +audio.comfy-audio.empty-audio-widget { + display: none; +} + +#vue-app { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; +} + +/* Set auto complete panel's width as it is not accessible within vue-root */ +.p-autocomplete-overlay { + max-width: 25vw; +} + +.p-tree-node-content { + padding: var(--comfy-tree-explorer-item-padding) !important; +} + +/* Load3d styles */ +.comfy-load-3d, +.comfy-load-3d-animation, +.comfy-preview-3d, +.comfy-preview-3d-animation { + display: flex; + flex-direction: column; + background: transparent; + flex: 1; + position: relative; + overflow: hidden; +} + +.comfy-load-3d canvas, +.comfy-load-3d-animation canvas, +.comfy-preview-3d canvas, +.comfy-preview-3d-animation canvas, +.comfy-load-3d-viewer canvas { + display: flex; + width: 100% !important; + height: 100% !important; +} + +/* End of Load3d styles */ + +/* [Desktop] Electron window specific styles */ +.app-drag { + app-region: drag; +} + +.no-drag { + app-region: no-drag; +} + +.window-actions-spacer { + width: calc(100vw - env(titlebar-area-width, 100vw)); +} +/* End of [Desktop] Electron window specific styles */ + +.lg-node { + /* Disable text selection on all nodes */ + user-select: none; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; +} + +.lg-node .lg-slot, +.lg-node .lg-widget { + transition: + opacity 0.1s ease, + font-size 0.1s ease; +} + +/* Performance optimization during canvas interaction */ +.transform-pane--interacting .lg-node * { + transition: none !important; +} + +.transform-pane--interacting .lg-node { + will-change: transform; +} + +/* START LOD specific styles */ +/* LOD styles - Custom CSS avoids 100+ Tailwind selectors that would slow style recalculation when .isLOD toggles */ + +.isLOD .lg-node { + box-shadow: none; + filter: none; + backdrop-filter: none; + text-shadow: none; + -webkit-mask-image: none; + mask-image: none; + clip-path: none; + background-image: none; + text-rendering: optimizeSpeed; + border-radius: 0; + contain: layout style; + transition: none; +} + +.isLOD .lg-node-widgets { + pointer-events: none; +} + +.lod-toggle { + visibility: visible; +} + +.isLOD .lod-toggle { + visibility: hidden; +} + +.lod-fallback { + display: none; +} + +.isLOD .lod-fallback { + display: block; +} + +.isLOD .image-preview img { + image-rendering: pixelated; +} + +.isLOD .slot-dot { + border-radius: 0; +} +/* END LOD specific styles */ diff --git a/build/customIconCollection.ts b/packages/design-system/src/iconCollection.ts similarity index 96% rename from build/customIconCollection.ts rename to packages/design-system/src/iconCollection.ts index f2d823ed5..170a5465f 100644 --- a/build/customIconCollection.ts +++ b/packages/design-system/src/iconCollection.ts @@ -5,7 +5,7 @@ import { fileURLToPath } from 'url' const fileName = fileURLToPath(import.meta.url) const dirName = dirname(fileName) -const customIconsPath = join(dirName, '..', 'src', 'assets', 'icons', 'custom') +const customIconsPath = join(dirName, 'icons') // Iconify collection structure interface IconifyIcon { diff --git a/src/assets/icons/README.md b/packages/design-system/src/icons/README.md similarity index 95% rename from src/assets/icons/README.md rename to packages/design-system/src/icons/README.md index b01a3e3ef..ba7cdb3e4 100644 --- a/src/assets/icons/README.md +++ b/packages/design-system/src/icons/README.md @@ -51,7 +51,7 @@ ComfyUI supports three types of icons that can be used throughout the interface. ```vue