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
-
+
@@ -128,10 +128,10 @@ ComfyUI supports three types of icons that can be used throughout the interface.
### 1. Add Your SVG
-Place your SVG file in `src/assets/icons/custom/`:
+Place your SVG file in `packages/design-system/src/icons/`:
```
-src/assets/icons/custom/
+packages/design-system/src/icons/
├── workflow-duplicate.svg
├── node-preview.svg
└── your-icon.svg
@@ -249,8 +249,8 @@ Icons are automatically imported using `unplugin-icons` - no manual imports need
The icon system has two layers:
-1. **Build-time Processing** (`build/customIconCollection.ts`):
- - Scans `src/assets/icons/custom/` for SVG files
+1. **Build-time Processing** (`packages/design-system/src/iconCollection.ts`):
+ - Scans `packages/design-system/src/icons/` for SVG files
- Validates SVG content and structure
- Creates Iconify collection for Tailwind CSS
- Provides error handling for malformed files
@@ -273,7 +273,7 @@ export const iconCollection: IconifyCollection = {
Icons({
compiler: 'vue3',
customCollections: {
- comfy: FileSystemIconLoader('src/assets/icons/custom')
+ comfy: FileSystemIconLoader('packages/design-system/src/icons')
}
})
```
diff --git a/src/assets/icons/custom/ai-model.svg b/packages/design-system/src/icons/ai-model.svg
similarity index 100%
rename from src/assets/icons/custom/ai-model.svg
rename to packages/design-system/src/icons/ai-model.svg
diff --git a/src/assets/icons/custom/mask.svg b/packages/design-system/src/icons/mask.svg
similarity index 100%
rename from src/assets/icons/custom/mask.svg
rename to packages/design-system/src/icons/mask.svg
diff --git a/src/assets/icons/custom/node.svg b/packages/design-system/src/icons/node.svg
similarity index 100%
rename from src/assets/icons/custom/node.svg
rename to packages/design-system/src/icons/node.svg
diff --git a/src/assets/icons/custom/template.svg b/packages/design-system/src/icons/template.svg
similarity index 100%
rename from src/assets/icons/custom/template.svg
rename to packages/design-system/src/icons/template.svg
diff --git a/src/assets/icons/custom/workflow.svg b/packages/design-system/src/icons/workflow.svg
similarity index 100%
rename from src/assets/icons/custom/workflow.svg
rename to packages/design-system/src/icons/workflow.svg
diff --git a/packages/design-system/tailwind.config.ts b/packages/design-system/tailwind.config.ts
new file mode 100644
index 000000000..d287e86c3
--- /dev/null
+++ b/packages/design-system/tailwind.config.ts
@@ -0,0 +1,26 @@
+import lucide from '@iconify-json/lucide/icons.json' with { type: 'json' }
+import { addDynamicIconSelectors } from '@iconify/tailwind'
+
+import { iconCollection } from './src/iconCollection'
+
+export default {
+ content: [],
+ safelist: [
+ 'icon-[lucide--folder]',
+ 'icon-[lucide--package]',
+ 'icon-[lucide--image]',
+ 'icon-[lucide--video]',
+ 'icon-[lucide--box]',
+ 'icon-[lucide--audio-waveform]',
+ 'icon-[lucide--message-circle]'
+ ],
+ plugins: [
+ addDynamicIconSelectors({
+ iconSets: {
+ comfy: iconCollection,
+ lucide
+ },
+ prefix: 'icon'
+ })
+ ]
+}
diff --git a/packages/design-system/tsconfig.json b/packages/design-system/tsconfig.json
new file mode 100644
index 000000000..60c7df181
--- /dev/null
+++ b/packages/design-system/tsconfig.json
@@ -0,0 +1,8 @@
+{
+ "extends": "../../tsconfig.json",
+ "compilerOptions": {
+ "rootDir": "src",
+ "outDir": "dist"
+ },
+ "include": ["src/**/*"]
+}
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 69032f4ec..2fb5c1a7d 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -17,6 +17,9 @@ importers:
'@comfyorg/comfyui-electron-types':
specifier: 0.4.73-0
version: 0.4.73-0
+ '@comfyorg/design-system':
+ specifier: workspace:*
+ version: link:packages/design-system
'@comfyorg/tailwind-utils':
specifier: workspace:*
version: link:packages/tailwind-utils
@@ -174,12 +177,6 @@ importers:
'@eslint/js':
specifier: ^9.35.0
version: 9.35.0
- '@iconify-json/lucide':
- specifier: ^1.2.66
- version: 1.2.66
- '@iconify/tailwind':
- specifier: ^1.2.0
- version: 1.2.0
'@intlify/eslint-plugin-vue-i18n':
specifier: ^4.1.0
version: 4.1.0(eslint@9.35.0(jiti@2.4.2))(jsonc-eslint-parser@2.4.0)(vue-eslint-parser@10.2.0(eslint@9.35.0(jiti@2.4.2)))(yaml-eslint-parser@1.3.0)
@@ -355,6 +352,22 @@ importers:
specifier: ^3.24.1
version: 3.24.1(zod@3.24.1)
+ packages/design-system:
+ dependencies:
+ '@iconify-json/lucide':
+ specifier: ^1.1.178
+ version: 1.2.66
+ '@iconify/tailwind':
+ specifier: ^1.1.3
+ version: 1.2.0
+ devDependencies:
+ tailwindcss:
+ specifier: ^3.4.17
+ version: 3.4.17
+ typescript:
+ specifier: ^5.4.5
+ version: 5.9.2
+
packages/tailwind-utils:
dependencies:
clsx:
@@ -3116,10 +3129,16 @@ packages:
resolution: {integrity: sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==}
engines: {node: '>=12'}
+ any-promise@1.3.0:
+ resolution: {integrity: sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==}
+
anymatch@3.1.3:
resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==}
engines: {node: '>= 8'}
+ arg@5.0.2:
+ resolution: {integrity: sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==}
+
argparse@1.0.10:
resolution: {integrity: sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==}
@@ -3295,6 +3314,10 @@ packages:
camel-case@4.1.2:
resolution: {integrity: sha512-gxGWBrTT1JuMx6R+o5PTXMmUnhnVzLQ9SNutD4YqKtI6ap897t3tKECYla6gCWEkplXnlNybEkZg9GEGxKFCgw==}
+ camelcase-css@2.0.1:
+ resolution: {integrity: sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==}
+ engines: {node: '>= 6'}
+
camelcase@8.0.0:
resolution: {integrity: sha512-8WB3Jcas3swSvjIeA2yvCJ+Miyz5l1ZmB6HFb9R1317dt9LCQoswg/BGrmAmkWVEszSrrg4RwmO46qIm2OEnSA==}
engines: {node: '>=16'}
@@ -3424,6 +3447,10 @@ packages:
commander@2.20.3:
resolution: {integrity: sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==}
+ commander@4.1.1:
+ resolution: {integrity: sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==}
+ engines: {node: '>= 6'}
+
commander@8.3.0:
resolution: {integrity: sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==}
engines: {node: '>= 12'}
@@ -3629,6 +3656,9 @@ packages:
devlop@1.1.0:
resolution: {integrity: sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA==}
+ didyoumean@1.2.2:
+ resolution: {integrity: sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==}
+
diff-match-patch@1.0.5:
resolution: {integrity: sha512-IayShXAgj/QMXgB0IWmKx+rOPuGMhqm5w6jvFxmVenXKIzRqTAAsbBPT3kWQeGANj3jGgvcvv4yK6SxqYmikgw==}
@@ -3636,6 +3666,9 @@ packages:
resolution: {integrity: sha512-7SCDfnQtBObcngVXNPZcnxGxqqPTK4UqeXeKAch+RGH5qpqadWbV9FmN71x9Bb4tTs0TNFb4FT/4Kz4P4Cjqcw==}
engines: {node: '>=6.0.0'}
+ dlv@1.1.3:
+ resolution: {integrity: sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==}
+
doctypes@1.1.0:
resolution: {integrity: sha512-LLBi6pEqS6Do3EKQ3J0NqHWV5hhb78Pi8vvESYwyOy2c31ZEZVdtitdzsQsKb7878PEERhzUk0ftqGhG6Mz+pQ==}
@@ -4524,6 +4557,10 @@ packages:
resolution: {integrity: sha512-LUU2Gx8EhYxpdzTR6BmjL1ifgOAQJQELTHOiPv9KITaKjZvJ9Jmgigx01tuZ49id37LorpGc9dPBPlXTboXScw==}
engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0}
+ jiti@1.21.7:
+ resolution: {integrity: sha512-/imKNG4EbWNrVjoNC/1H5/9GFy+tqjGBHCaSsN+P2RnPqjsLmv6UD3Ej+Kj8nBWaRAwyk7kK5ZUc+OEatnTR3A==}
+ hasBin: true
+
jiti@2.4.2:
resolution: {integrity: sha512-rg9zJN+G4n2nfJl5MW3BMygZX56zKPNVEYYqq7adpmMh4Jn2QNEwhvQlFy6jPVdcod7txZtKHWnyZiA3a0zP7A==}
hasBin: true
@@ -4747,6 +4784,10 @@ packages:
resolution: {integrity: sha512-eop+wDAvpItUys0FWkHIKeC9ybYrTGbU41U5K7+bttZZeohvnY7M9dZ5kB21GNWiFT2q1OoPTvncPCgSOVO5ow==}
engines: {node: '>=14'}
+ lilconfig@3.1.3:
+ resolution: {integrity: sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw==}
+ engines: {node: '>=14'}
+
lines-and-columns@1.2.4:
resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==}
@@ -5109,6 +5150,9 @@ packages:
resolution: {integrity: sha512-SsI/exkodHsh+ofCV7An2PZWRaJC7eFVl7gtHQlMWFEDmWtb7cELr/GK32Nhe/6dZQhbr81o+Moswx9aXN3RRg==}
engines: {node: '>=18.2.0'}
+ mz@2.7.0:
+ resolution: {integrity: sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==}
+
nanoid@3.3.8:
resolution: {integrity: sha512-WNLf5Sd8oZxOm+TzppcYk8gVOgP+l58xNy58D0nbUnOxOWRWvlcCV4kUF7ltmI6PsrLl/BgKEyS4mqsGChFN0w==}
engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1}
@@ -5200,6 +5244,10 @@ packages:
resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==}
engines: {node: '>=0.10.0'}
+ object-hash@3.0.0:
+ resolution: {integrity: sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==}
+ engines: {node: '>= 6'}
+
object-keys@1.1.1:
resolution: {integrity: sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==}
engines: {node: '>= 0.4'}
@@ -5375,6 +5423,10 @@ packages:
engines: {node: '>=0.10'}
hasBin: true
+ pify@2.3.0:
+ resolution: {integrity: sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==}
+ engines: {node: '>=0.10.0'}
+
pinia@2.2.2:
resolution: {integrity: sha512-ja2XqFWZC36mupU4z1ZzxeTApV7DOw44cV4dhQ9sGwun+N89v/XP7+j7q6TanS1u1tdbK4r+1BUx7heMaIdagA==}
peerDependencies:
@@ -5387,6 +5439,10 @@ packages:
typescript:
optional: true
+ pirates@4.0.7:
+ resolution: {integrity: sha512-TfySrs/5nm8fQJDcBDuUng3VOUKsd7S+zqvbOTiGXHfxX4wK31ard+hoNuvkicM/2YFzlpDgABOevKSsB4G/FA==}
+ engines: {node: '>= 6'}
+
pkg-types@1.3.1:
resolution: {integrity: sha512-/Jm5M4RvtBFVkKWRu2BLUTNP8/M2a+UwuAX+ae4770q1qVGtfjG+WTCupoZixokjmHiry8uI+dlY8KXYV5HVVQ==}
@@ -5403,10 +5459,47 @@ packages:
engines: {node: '>=18'}
hasBin: true
+ postcss-import@15.1.0:
+ resolution: {integrity: sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew==}
+ engines: {node: '>=14.0.0'}
+ peerDependencies:
+ postcss: ^8.0.0
+
+ postcss-js@4.1.0:
+ resolution: {integrity: sha512-oIAOTqgIo7q2EOwbhb8UalYePMvYoIeRY2YKntdpFQXNosSu3vLrniGgmH9OKs/qAkfoj5oB3le/7mINW1LCfw==}
+ engines: {node: ^12 || ^14 || >= 16}
+ peerDependencies:
+ postcss: ^8.4.21
+
+ postcss-load-config@4.0.2:
+ resolution: {integrity: sha512-bSVhyJGL00wMVoPUzAVAnbEoWyqRxkjv64tUl427SKnPrENtq6hJwUojroMz2VB+Q1edmi4IfrAPpami5VVgMQ==}
+ engines: {node: '>= 14'}
+ peerDependencies:
+ postcss: '>=8.0.9'
+ ts-node: '>=9.0.0'
+ peerDependenciesMeta:
+ postcss:
+ optional: true
+ ts-node:
+ optional: true
+
+ postcss-nested@6.2.0:
+ resolution: {integrity: sha512-HQbt28KulC5AJzG+cZtj9kvKB93CFCdLvog1WFLf1D+xmMvPGlBstkpTEZfK5+AN9hfJocyBFCNiqyS48bpgzQ==}
+ engines: {node: '>=12.0'}
+ peerDependencies:
+ postcss: ^8.2.14
+
postcss-selector-parser@6.1.0:
resolution: {integrity: sha512-UMz42UD0UY0EApS0ZL9o1XnLhSTtvvvLe5Dc2H2O56fvRZi+KulDyf5ctDhhtYJBGKStV2FL1fy6253cmLgqVQ==}
engines: {node: '>=4'}
+ postcss-selector-parser@6.1.2:
+ resolution: {integrity: sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==}
+ engines: {node: '>=4'}
+
+ postcss-value-parser@4.2.0:
+ resolution: {integrity: sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==}
+
postcss@8.5.1:
resolution: {integrity: sha512-6oz2beyjc5VMn/KV1pPw8fliQkhBXrVn1Z3TVyqZxU8kZpzEKhBdmCFqI6ZbmGtamQvQGuU1sgPTk8ZrXDD7jQ==}
engines: {node: ^10 || ^12 || >=14}
@@ -5603,6 +5696,9 @@ packages:
resolution: {integrity: sha512-w8nqGImo45dmMIfljjMwOGtbmC/mk4CMYhWIicdSflH91J9TyCyczcPFXJzrZ/ZXcgGRFeP6BU0BEJTw6tZdfQ==}
engines: {node: '>=0.10.0'}
+ read-cache@1.0.0:
+ resolution: {integrity: sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==}
+
readable-stream@2.3.8:
resolution: {integrity: sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==}
@@ -5924,6 +6020,11 @@ packages:
subscribable-things@2.1.53:
resolution: {integrity: sha512-zWvN9F/eYQWDKszXl4NXkyqPXvMDZDmXfcHiM5C5WQZTTY2OK+2TZeDlA9oio69FEPqPu9T6yeEcAhQ2uRmnaw==}
+ sucrase@3.35.0:
+ resolution: {integrity: sha512-8EbVDiu9iN/nESwxeSxDKe0dunta1GOlHufmSSXxMD2z2/tMZpDMpvXQGsc+ajGo8y2uYUmixaSRUc/QPoQ0GA==}
+ engines: {node: '>=16 || 14 >=14.17'}
+ hasBin: true
+
superjson@2.2.2:
resolution: {integrity: sha512-5JRxVqC8I8NuOUjzBbvVJAKNM8qoVuH0O77h4WInc/qC2q5IreqKxYwgkga3PfA22OayK2ikceb/B26dztPl+Q==}
engines: {node: '>=16'}
@@ -5964,6 +6065,11 @@ packages:
peerDependencies:
tailwindcss: '>=3.1.0'
+ tailwindcss@3.4.17:
+ resolution: {integrity: sha512-w33E2aCvSDP0tW9RZuNXadXlkHXqFzSkQew/aIa2i/Sj8fThxwovwlXHSPXTbAHwEIhBFXAedUhP2tueAKP8Og==}
+ engines: {node: '>=14.0.0'}
+ hasBin: true
+
tailwindcss@4.1.12:
resolution: {integrity: sha512-DzFtxOi+7NsFf7DBtI3BJsynR+0Yp6etH+nRPTbpWnS2pZBaSksv/JGctNwSWzbFjp0vxSqknaUylseZqMDGrA==}
@@ -5988,6 +6094,13 @@ packages:
resolution: {integrity: sha512-pFYqmTw68LXVjeWJMST4+borgQP2AyMNbg1BpZh9LbyhUeNkeaPF9gzfPGUAnSMV3qPYdWUwDIjjCLiSDOl7vg==}
engines: {node: '>=18'}
+ thenify-all@1.6.0:
+ resolution: {integrity: sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==}
+ engines: {node: '>=0.8'}
+
+ thenify@3.3.1:
+ resolution: {integrity: sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==}
+
three@0.170.0:
resolution: {integrity: sha512-FQK+LEpYc0fBD+J8g6oSEyyNzjp+Q7Ks1C568WWaoMRLW+TkNNWmenWeGgJjV105Gd+p/2ql1ZcjYvNiPZBhuQ==}
@@ -6074,6 +6187,9 @@ packages:
resolution: {integrity: sha512-q5W7tVM71e2xjHZTlgfTDoPF/SmqKG5hddq9SzR49CH2hayqRKJtQ4mtRlSxKaJlR/+9rEM+mnBHf7I2/BQcpQ==}
engines: {node: '>=6.10'}
+ ts-interface-checker@0.1.13:
+ resolution: {integrity: sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==}
+
ts-map@1.0.3:
resolution: {integrity: sha512-vDWbsl26LIcPGmDpoVzjEP6+hvHZkBkLW7JpvwbCv/5IYPJlsbzCVXY3wsCeAxAUeTclNOUZxnLdGh3VBD/J6w==}
@@ -9905,11 +10021,15 @@ snapshots:
ansi-styles@6.2.1: {}
+ any-promise@1.3.0: {}
+
anymatch@3.1.3:
dependencies:
normalize-path: 3.0.0
picomatch: 2.3.1
+ arg@5.0.2: {}
+
argparse@1.0.10:
dependencies:
sprintf-js: 1.0.3
@@ -10115,6 +10235,8 @@ snapshots:
pascal-case: 3.1.2
tslib: 2.8.1
+ camelcase-css@2.0.1: {}
+
camelcase@8.0.0: {}
caniuse-lite@1.0.30001737: {}
@@ -10228,6 +10350,8 @@ snapshots:
commander@2.20.3: {}
+ commander@4.1.1: {}
+
commander@8.3.0: {}
compare-versions@6.1.1: {}
@@ -10410,6 +10534,8 @@ snapshots:
dependencies:
dequal: 2.0.3
+ didyoumean@1.2.2: {}
+
diff-match-patch@1.0.5: {}
dirty-json@0.9.2:
@@ -10418,6 +10544,8 @@ snapshots:
unescape-js: 1.1.4
utf8: 3.0.0
+ dlv@1.1.3: {}
+
doctypes@1.1.0: {}
dom-accessibility-api@0.5.16: {}
@@ -11367,6 +11495,8 @@ snapshots:
chalk: 4.1.2
pretty-format: 30.0.5
+ jiti@1.21.7: {}
+
jiti@2.4.2: {}
jiti@2.5.1: {}
@@ -11588,6 +11718,8 @@ snapshots:
lilconfig@3.1.2: {}
+ lilconfig@3.1.3: {}
+
lines-and-columns@1.2.4: {}
lines-and-columns@2.0.3: {}
@@ -12144,6 +12276,12 @@ snapshots:
'@babel/runtime': 7.28.4
tslib: 2.8.1
+ mz@2.7.0:
+ dependencies:
+ any-promise: 1.3.0
+ object-assign: 4.1.1
+ thenify-all: 1.6.0
+
nanoid@3.3.8: {}
nanoid@5.1.5: {}
@@ -12257,6 +12395,8 @@ snapshots:
object-assign@4.1.1: {}
+ object-hash@3.0.0: {}
+
object-keys@1.1.1: {}
ohash@2.0.11: {}
@@ -12447,6 +12587,8 @@ snapshots:
pidtree@0.6.0: {}
+ pify@2.3.0: {}
+
pinia@2.2.2(typescript@5.9.2)(vue@3.5.13(typescript@5.9.2)):
dependencies:
'@vue/devtools-api': 6.6.3
@@ -12455,6 +12597,8 @@ snapshots:
optionalDependencies:
typescript: 5.9.2
+ pirates@4.0.7: {}
+
pkg-types@1.3.1:
dependencies:
confbox: 0.1.8
@@ -12475,11 +12619,42 @@ snapshots:
optionalDependencies:
fsevents: 2.3.2
+ postcss-import@15.1.0(postcss@8.5.1):
+ dependencies:
+ postcss: 8.5.1
+ postcss-value-parser: 4.2.0
+ read-cache: 1.0.0
+ resolve: 1.22.10
+
+ postcss-js@4.1.0(postcss@8.5.1):
+ dependencies:
+ camelcase-css: 2.0.1
+ postcss: 8.5.1
+
+ postcss-load-config@4.0.2(postcss@8.5.1):
+ dependencies:
+ lilconfig: 3.1.3
+ yaml: 2.8.1
+ optionalDependencies:
+ postcss: 8.5.1
+
+ postcss-nested@6.2.0(postcss@8.5.1):
+ dependencies:
+ postcss: 8.5.1
+ postcss-selector-parser: 6.1.2
+
postcss-selector-parser@6.1.0:
dependencies:
cssesc: 3.0.0
util-deprecate: 1.0.2
+ postcss-selector-parser@6.1.2:
+ dependencies:
+ cssesc: 3.0.0
+ util-deprecate: 1.0.2
+
+ postcss-value-parser@4.2.0: {}
+
postcss@8.5.1:
dependencies:
nanoid: 3.3.8
@@ -12755,6 +12930,10 @@ snapshots:
react@19.1.1: {}
+ read-cache@1.0.0:
+ dependencies:
+ pify: 2.3.0
+
readable-stream@2.3.8:
dependencies:
core-util-is: 1.0.3
@@ -13137,6 +13316,16 @@ snapshots:
rxjs-interop: 2.0.0
tslib: 2.8.1
+ sucrase@3.35.0:
+ dependencies:
+ '@jridgewell/gen-mapping': 0.3.13
+ commander: 4.1.1
+ glob: 10.4.5
+ lines-and-columns: 1.2.4
+ mz: 2.7.0
+ pirates: 4.0.7
+ ts-interface-checker: 0.1.13
+
superjson@2.2.2:
dependencies:
copy-anything: 3.0.5
@@ -13174,6 +13363,33 @@ snapshots:
dependencies:
tailwindcss: 4.1.12
+ tailwindcss@3.4.17:
+ dependencies:
+ '@alloc/quick-lru': 5.2.0
+ arg: 5.0.2
+ chokidar: 3.6.0
+ didyoumean: 1.2.2
+ dlv: 1.1.3
+ fast-glob: 3.3.3
+ glob-parent: 6.0.2
+ is-glob: 4.0.3
+ jiti: 1.21.7
+ lilconfig: 3.1.3
+ micromatch: 4.0.8
+ normalize-path: 3.0.0
+ object-hash: 3.0.0
+ picocolors: 1.1.1
+ postcss: 8.5.1
+ postcss-import: 15.1.0(postcss@8.5.1)
+ postcss-js: 4.1.0(postcss@8.5.1)
+ postcss-load-config: 4.0.2(postcss@8.5.1)
+ postcss-nested: 6.2.0(postcss@8.5.1)
+ postcss-selector-parser: 6.1.2
+ resolve: 1.22.10
+ sucrase: 3.35.0
+ transitivePeerDependencies:
+ - ts-node
+
tailwindcss@4.1.12: {}
tapable@2.2.3: {}
@@ -13208,6 +13424,14 @@ snapshots:
glob: 10.4.5
minimatch: 9.0.5
+ thenify-all@1.6.0:
+ dependencies:
+ thenify: 3.3.1
+
+ thenify@3.3.1:
+ dependencies:
+ any-promise: 1.3.0
+
three@0.170.0: {}
tiny-invariant@1.3.3: {}
@@ -13273,6 +13497,8 @@ snapshots:
ts-dedent@2.2.0: {}
+ ts-interface-checker@0.1.13: {}
+
ts-map@1.0.3: {}
tsconfig-paths@4.2.0:
diff --git a/src/assets/css/style.css b/src/assets/css/style.css
index d331541f7..627b129e4 100644
--- a/src/assets/css/style.css
+++ b/src/assets/css/style.css
@@ -1,1006 +1 @@
-@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 */
+@import '@comfyorg/design-system/css/style.css';
\ No newline at end of file
diff --git a/tailwind.config.ts b/tailwind.config.ts
index 98c7c4ea0..ae57cde6a 100644
--- a/tailwind.config.ts
+++ b/tailwind.config.ts
@@ -1,28 +1,6 @@
-import lucide from '@iconify-json/lucide/icons.json' with { type: 'json' }
-import { addDynamicIconSelectors } from '@iconify/tailwind'
-
-import { iconCollection } from './build/customIconCollection'
+import baseConfig from '@comfyorg/design-system/tailwind-config'
export default {
- content: ['./index.html', './src/**/*.{vue,js,ts,jsx,tsx}'],
-
- safelist: [
- 'icon-[lucide--folder]',
- 'icon-[lucide--package]',
- 'icon-[lucide--image]',
- 'icon-[lucide--video]',
- 'icon-[lucide--box]',
- 'icon-[lucide--audio-waveform]',
- 'icon-[lucide--message-circle]'
- ],
-
- plugins: [
- addDynamicIconSelectors({
- iconSets: {
- comfy: iconCollection,
- lucide
- },
- prefix: 'icon'
- })
- ]
+ ...baseConfig,
+ content: ['./index.html', './src/**/*.{vue,js,ts,jsx,tsx}']
}
diff --git a/tsconfig.json b/tsconfig.json
index 75926b943..3af5495b6 100644
--- a/tsconfig.json
+++ b/tsconfig.json
@@ -37,5 +37,6 @@
"src/**/*",
"src/types/**/*.d.ts",
"tests-ui/**/*",
+ "tailwind.config.ts"
]
}
diff --git a/vite.config.mts b/vite.config.mts
index 25cd730aa..9c50268a9 100644
--- a/vite.config.mts
+++ b/vite.config.mts
@@ -133,7 +133,7 @@ export default defineConfig({
Icons({
compiler: 'vue3',
customCollections: {
- comfy: FileSystemIconLoader('src/assets/icons/custom')
+ comfy: FileSystemIconLoader('packages/design-system/src/icons')
}
}),
diff --git a/vitest.config.ts b/vitest.config.ts
index 02565497e..244aae16f 100644
--- a/vitest.config.ts
+++ b/vitest.config.ts
@@ -9,7 +9,7 @@ export default defineConfig({
Icons({
compiler: 'vue3',
customCollections: {
- comfy: FileSystemIconLoader('src/assets/icons/custom')
+ comfy: FileSystemIconLoader('packages/design-system/src/icons')
}
})
],