Files
ComfyUI_frontend/src/assets/css/style.css
Christian Byrne 8c6ee026c0 fix: Set Vue node initial size in layout store instead of CSS (#5571)
* fix: Vue nodes now respect deserialized width from LiteGraph

* fix: Set Vue node initial size in layout store instead of CSS

Vue nodes now properly set their initial size in the layout store using
the resize() function from useNodeLayout on component mount. This ensures
the layout store is the single source of truth for sizing, preventing
conflicts with the ResizeObserver that was overriding CSS-based sizing.

This resolves the issue where Vue nodes would shrink to minimal size
after user interaction due to ResizeObserver feedback loops.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>

* fix: Remove duplicate onMounted call in LGraphNode.vue

---------

Co-authored-by: Claude <noreply@anthropic.com>
2025-09-14 20:46:43 -07:00

1008 lines
20 KiB
CSS

@layer theme, base, primevue, components, utilities;
@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);
/* Palette Colors */
--color-charcoal-100: #171718;
--color-charcoal-200: #202121;
--color-charcoal-300: #262729;
--color-charcoal-400: #2d2e32;
--color-charcoal-500: #313235;
--color-charcoal-600: #3c3d42;
--color-charcoal-700: #494a50;
--color-charcoal-800: #55565e;
--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-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-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-800) r g b/ 0.15);
--color-node-hover-200: rgb(from var(--color-charcoal-800) 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-300);
--color-node-component-surface-highlight: var(--color-slate-100);
--color-node-component-surface-hovered: var(--color-charcoal-500);
--color-node-component-surface-selected: var(--color-charcoal-700);
--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 */
/* Vue Node LOD (Level of Detail) System */
/* These classes control rendering detail based on zoom level */
/* Minimal LOD (zoom <= 0.4) - Title only for performance */
.lg-node--lod-minimal {
min-height: 32px;
transition: min-height 0.2s ease;
/* Performance optimizations */
text-shadow: none;
backdrop-filter: none;
}
.lg-node--lod-minimal .lg-node-body {
display: none !important;
}
/* Reduced LOD (0.4 < zoom <= 0.8) - Essential widgets, simplified styling */
.lg-node--lod-reduced {
transition: opacity 0.1s ease;
/* Performance optimizations */
text-shadow: none;
}
.lg-node--lod-reduced .lg-widget-label,
.lg-node--lod-reduced .lg-slot-label {
display: none;
}
.lg-node--lod-reduced .lg-slot {
opacity: 0.6;
font-size: 0.75rem;
}
.lg-node--lod-reduced .lg-widget {
margin: 2px 0;
font-size: 0.875rem;
}
/* Full LOD (zoom > 0.8) - Complete detail rendering */
.lg-node--lod-full {
/* Uses default styling - no overrides needed */
}
.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;
}
/* Global performance optimizations for LOD */
.lg-node--lod-minimal,
.lg-node--lod-reduced {
/* Remove ALL expensive paint effects */
box-shadow: none !important;
filter: none !important;
backdrop-filter: none !important;
text-shadow: none !important;
-webkit-mask-image: none !important;
mask-image: none !important;
clip-path: none !important;
}
/* Reduce paint complexity for minimal LOD */
.lg-node--lod-minimal {
/* Skip complex borders */
border-radius: 0 !important;
/* Use solid colors only */
background-image: none !important;
}