Lint: Add tailwind linter (#5984)

## Summary

Adds the [tailwind lint
plugin](https://github.com/francoismassart/eslint-plugin-tailwindcss/?tab=readme-ov-file#eslint-plugin-tailwindcss)
and fixes the currently fixable rules ([v4 is still in
beta](https://github.com/francoismassart/eslint-plugin-tailwindcss/?tab=readme-ov-file#about-tailwind-css-4-support)).

## Changes

- **What**: Enforces things like consistent class order, and eventually
can prohibit extra classes that could be utilities instead
- **Dependencies**: The plugin and its types

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-5984-Lint-Add-tailwind-linter-2866d73d365081d89db0d998232533bb)
by [Unito](https://www.unito.io)

---------

Co-authored-by: GitHub Action <action@github.com>
This commit is contained in:
Alexander Brown
2025-10-08 19:39:14 -07:00
committed by GitHub
parent c9da8b200d
commit b943c0fa75
177 changed files with 731 additions and 652 deletions

View File

@@ -4,36 +4,67 @@ import pluginI18n from '@intlify/eslint-plugin-vue-i18n'
import { importX } from 'eslint-plugin-import-x'
import eslintPluginPrettierRecommended from 'eslint-plugin-prettier/recommended'
import storybook from 'eslint-plugin-storybook'
import tailwind from 'eslint-plugin-tailwindcss'
import unusedImports from 'eslint-plugin-unused-imports'
import pluginVue from 'eslint-plugin-vue'
import { defineConfig } from 'eslint/config'
import globals from 'globals'
import tseslint from 'typescript-eslint'
import {
configs as tseslintConfigs,
parser as tseslintParser
} from 'typescript-eslint'
import vueParser from 'vue-eslint-parser'
const extraFileExtensions = ['.vue']
const commonGlobals = {
...globals.browser,
__COMFYUI_FRONTEND_VERSION__: 'readonly'
} as const
const settings = {
'import/resolver': {
typescript: true,
node: true
},
tailwindcss: {
config: `${import.meta.dirname}/packages/design-system/src/css/style.css`,
functions: ['cn', 'clsx', 'tw']
}
} as const
const commonParserOptions = {
parser: tseslintParser,
projectService: true,
tsConfigRootDir: import.meta.dirname,
ecmaVersion: 2020,
sourceType: 'module',
extraFileExtensions
} as const
export default defineConfig([
{
ignores: [
'src/scripts/*',
'src/extensions/core/*',
'src/types/vue-shim.d.ts',
'packages/registry-types/src/comfyRegistryTypes.ts',
'src/types/generatedManagerTypes.ts',
'.i18nrc.cjs',
'components.d.ts',
'lint-staged.config.js',
'vitest.setup.ts',
'**/vite.config.*.timestamp*',
'**/vitest.config.*.timestamp*'
'**/vitest.config.*.timestamp*',
'packages/registry-types/src/comfyRegistryTypes.ts',
'src/extensions/core/*',
'src/scripts/*',
'src/types/generatedManagerTypes.ts',
'src/types/vue-shim.d.ts'
]
},
{
files: ['./**/*.{ts,mts}'],
settings,
languageOptions: {
globals: {
...globals.browser,
__COMFYUI_FRONTEND_VERSION__: 'readonly'
},
globals: commonGlobals,
parserOptions: {
parser: tseslint.parser,
...commonParserOptions,
projectService: {
allowDefaultProject: [
'vite.config.mts',
@@ -42,47 +73,26 @@ export default defineConfig([
'playwright.config.ts',
'playwright.i18n.config.ts'
]
},
tsConfigRootDir: import.meta.dirname,
ecmaVersion: 2020,
sourceType: 'module',
extraFileExtensions
}
},
settings: {
'import/resolver': {
typescript: true,
node: true
}
}
},
{
files: ['./**/*.vue'],
settings,
languageOptions: {
globals: {
...globals.browser,
__COMFYUI_FRONTEND_VERSION__: 'readonly'
},
globals: commonGlobals,
parser: vueParser,
parserOptions: {
parser: tseslint.parser,
projectService: true,
tsConfigRootDir: import.meta.dirname,
ecmaVersion: 2020,
sourceType: 'module',
extraFileExtensions
}
},
settings: {
'import/resolver': {
typescript: true,
node: true
}
parserOptions: commonParserOptions
}
},
pluginJs.configs.recommended,
// eslint-disable-next-line import-x/no-named-as-default-member
tseslint.configs.recommended,
tseslintConfigs.recommended,
// Difference in typecheck on CI vs Local
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore Bad types in the plugin
tailwind.configs['flat/recommended'],
pluginVue.configs['flat/recommended'],
eslintPluginPrettierRecommended,
storybook.configs['flat/recommended'],
@@ -114,6 +124,7 @@ export default defineConfig([
'import-x/no-relative-packages': 'error',
'unused-imports/no-unused-imports': 'error',
'no-console': ['error', { allow: ['warn', 'error'] }],
'tailwindcss/no-custom-classname': 'off', // TODO: fix
'vue/no-v-html': 'off',
// Enforce dark-theme: instead of dark: prefix
'vue/no-restricted-class': ['error', '/^dark:/'],

View File

@@ -57,6 +57,7 @@
"@storybook/vue3-vite": "catalog:",
"@tailwindcss/vite": "catalog:",
"@trivago/prettier-plugin-sort-imports": "catalog:",
"@types/eslint-plugin-tailwindcss": "catalog:",
"@types/fs-extra": "catalog:",
"@types/jsdom": "catalog:",
"@types/node": "catalog:",
@@ -73,6 +74,7 @@
"eslint-plugin-import-x": "catalog:",
"eslint-plugin-prettier": "catalog:",
"eslint-plugin-storybook": "catalog:",
"eslint-plugin-tailwindcss": "catalog:",
"eslint-plugin-unused-imports": "catalog:",
"eslint-plugin-vue": "catalog:",
"fs-extra": "^11.2.0",

50
pnpm-lock.yaml generated
View File

@@ -84,6 +84,9 @@ catalogs:
'@trivago/prettier-plugin-sort-imports':
specifier: ^5.2.0
version: 5.2.2
'@types/eslint-plugin-tailwindcss':
specifier: ^3.17.0
version: 3.17.0
'@types/fs-extra':
specifier: ^11.0.4
version: 11.0.4
@@ -147,6 +150,9 @@ catalogs:
eslint-plugin-storybook:
specifier: ^9.1.6
version: 9.1.6
eslint-plugin-tailwindcss:
specifier: 4.0.0-beta.0
version: 4.0.0-beta.0
eslint-plugin-unused-imports:
specifier: ^4.2.0
version: 4.2.0
@@ -274,6 +280,9 @@ catalogs:
specifier: ^3.3.0
version: 3.3.0
overrides:
'@types/eslint': '-'
importers:
.:
@@ -489,6 +498,9 @@ importers:
'@trivago/prettier-plugin-sort-imports':
specifier: 'catalog:'
version: 5.2.2(@vue/compiler-sfc@3.5.13)(prettier@3.3.2)
'@types/eslint-plugin-tailwindcss':
specifier: 'catalog:'
version: 3.17.0
'@types/fs-extra':
specifier: 'catalog:'
version: 11.0.4
@@ -537,6 +549,9 @@ importers:
eslint-plugin-storybook:
specifier: 'catalog:'
version: 9.1.6(eslint@9.35.0(jiti@2.4.2))(storybook@9.1.6(@testing-library/dom@10.4.1)(prettier@3.3.2)(vite@5.4.19(@types/node@20.14.10)(lightningcss@1.30.1)(terser@5.39.2)))(typescript@5.9.2)
eslint-plugin-tailwindcss:
specifier: 'catalog:'
version: 4.0.0-beta.0(tailwindcss@4.1.12)
eslint-plugin-unused-imports:
specifier: 'catalog:'
version: 4.2.0(@typescript-eslint/eslint-plugin@8.44.0(@typescript-eslint/parser@8.44.0(eslint@9.35.0(jiti@2.4.2))(typescript@5.9.2))(eslint@9.35.0(jiti@2.4.2))(typescript@5.9.2))(eslint@9.35.0(jiti@2.4.2))
@@ -2990,6 +3005,9 @@ packages:
'@types/diff-match-patch@1.0.36':
resolution: {integrity: sha512-xFdR6tkm0MWvBfO8xXCSsinYxHcqkQUlcHeSpMC2ukzOb6lwQAfDmW+Qt0AvlGd8HpsS28qKsB+oPeJn9I39jg==}
'@types/eslint-plugin-tailwindcss@3.17.0':
resolution: {integrity: sha512-ucQGf2YIdTcndYcxRU3UdZgmhUHsOlbIF4BaRtl0op+7k2JmqM2i3aXZ6XIcfZgVq1ZKov7VM5c/BR81ukmkyg==}
'@types/estree@1.0.5':
resolution: {integrity: sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==}
@@ -4508,7 +4526,7 @@ packages:
resolution: {integrity: sha512-swNtI95SToIz05YINMA6Ox5R057IMAmWZ26GqPxusAp1TZzj+IdY9tXNWWD3vkF/wEqydCONcwjTFpxybBqZsg==}
engines: {node: ^14.18.0 || >=16.0.0}
peerDependencies:
'@types/eslint': '>=8.0.0'
'@types/eslint': '*'
eslint: '>=8.0.0'
eslint-config-prettier: '>= 7.0.0 <10.0.0 || >=10.1.0'
prettier: '>=3.0.0'
@@ -4525,6 +4543,12 @@ packages:
eslint: '>=8'
storybook: ^9.1.6
eslint-plugin-tailwindcss@4.0.0-beta.0:
resolution: {integrity: sha512-WWCajZgQu38Sd67ZCl2W6i3MRzqB0d+H8s4qV9iB6lBJbsDOIpIlj6R1Fj2FXkoWErbo05pZnZYbCGIU9o/DsA==}
engines: {node: '>=18.12.0'}
peerDependencies:
tailwindcss: ^3.4.0 || ^4.0.0
eslint-plugin-unused-imports@4.2.0:
resolution: {integrity: sha512-hLbJ2/wnjKq4kGA9AUaExVFIbNzyxYdVo49QZmKCnhk5pc9wcYRbfgLHvWJ8tnsdcseGhoUAddm9gn/lt+d74w==}
peerDependencies:
@@ -6966,6 +6990,11 @@ packages:
resolution: {integrity: sha512-9kY+CygyYM6j02t5YFHbNz2FN5QmYGv9zAjVp4lCDjlCw7amdckXlEt/bjMhUIfj4ThGRE4gCUH5+yGnNuPo5A==}
engines: {node: '>=10.0.0'}
tailwind-api-utils@1.0.3:
resolution: {integrity: sha512-KpzUHkH1ug1sq4394SLJX38ZtpeTiqQ1RVyFTTSY2XuHsNSTWUkRo108KmyyrMWdDbQrLYkSHaNKj/a3bmA4sQ==}
peerDependencies:
tailwindcss: ^3.3.0 || ^4.0.0 || ^4.0.0-beta
tailwind-merge@2.6.0:
resolution: {integrity: sha512-P+Vu1qXfzediirmHOC3xKGAYeZtPcV9g76X+xg2FD4tYgR71ewMA35Y3sCz3zhiN/dwefRpJX0yBcgwi1fXNQA==}
@@ -10336,6 +10365,8 @@ snapshots:
'@types/diff-match-patch@1.0.36': {}
'@types/eslint-plugin-tailwindcss@3.17.0': {}
'@types/estree@1.0.5': {}
'@types/estree@1.0.8': {}
@@ -10748,7 +10779,7 @@ snapshots:
'@vue/shared': 3.5.13
estree-walker: 2.0.2
magic-string: 0.30.19
postcss: 8.5.1
postcss: 8.5.6
source-map-js: 1.2.1
'@vue/compiler-ssr@3.5.13':
@@ -12097,6 +12128,14 @@ snapshots:
- supports-color
- typescript
eslint-plugin-tailwindcss@4.0.0-beta.0(tailwindcss@4.1.12):
dependencies:
fast-glob: 3.3.3
postcss: 8.5.6
synckit: 0.11.11
tailwind-api-utils: 1.0.3(tailwindcss@4.1.12)
tailwindcss: 4.1.12
eslint-plugin-unused-imports@4.2.0(@typescript-eslint/eslint-plugin@8.44.0(@typescript-eslint/parser@8.44.0(eslint@9.35.0(jiti@2.4.2))(typescript@5.9.2))(eslint@9.35.0(jiti@2.4.2))(typescript@5.9.2))(eslint@9.35.0(jiti@2.4.2)):
dependencies:
eslint: 9.35.0(jiti@2.4.2)
@@ -15115,6 +15154,13 @@ snapshots:
string-width: 4.2.3
strip-ansi: 6.0.1
tailwind-api-utils@1.0.3(tailwindcss@4.1.12):
dependencies:
enhanced-resolve: 5.18.3
jiti: 2.5.1
local-pkg: 1.1.2
tailwindcss: 4.1.12
tailwind-merge@2.6.0: {}
tailwindcss-primeui@0.6.1(tailwindcss@4.1.12):

View File

@@ -29,6 +29,7 @@ catalog:
'@storybook/vue3-vite': ^9.1.1
'@tailwindcss/vite': ^4.1.12
'@trivago/prettier-plugin-sort-imports': ^5.2.0
'@types/eslint-plugin-tailwindcss': ^3.17.0
'@types/fs-extra': ^11.0.4
'@types/jsdom': ^21.1.7
'@types/node': ^20.14.8
@@ -50,6 +51,7 @@ catalog:
eslint-plugin-import-x: ^4.16.1
eslint-plugin-prettier: ^5.5.4
eslint-plugin-storybook: ^9.1.6
eslint-plugin-tailwindcss: 4.0.0-beta.0
eslint-plugin-unused-imports: ^4.2.0
eslint-plugin-vue: ^10.4.0
firebase: ^11.6.0
@@ -95,6 +97,9 @@ catalog:
cleanupUnusedCatalogs: true
overrides:
'@types/eslint': '-'
ignoredBuiltDependencies:
- '@firebase/util'
- protobufjs

View File

@@ -2,7 +2,7 @@
<router-view />
<ProgressSpinner
v-if="isLoading"
class="absolute inset-0 flex justify-center items-center h-[unset]"
class="absolute inset-0 flex h-[unset] items-center justify-center"
/>
<GlobalDialog />
<BlockUI full-screen :blocked="isLoading" />

View File

@@ -1,17 +1,17 @@
<template>
<div class="flex flex-col h-full">
<div class="flex h-full flex-col">
<Tabs
:key="$i18n.locale"
v-model:value="bottomPanelStore.activeBottomPanelTabId"
>
<TabList pt:tab-list="border-none">
<div class="w-full flex justify-between">
<div class="flex w-full justify-between">
<div class="tabs-container">
<Tab
v-for="tab in bottomPanelStore.bottomPanelTabs"
:key="tab.id"
:value="tab.id"
class="p-3 border-none"
class="border-none p-3"
>
<span class="font-bold">
{{ getTabDisplayTitle(tab) }}
@@ -41,7 +41,7 @@
</TabList>
</Tabs>
<!-- h-0 to force the div to grow -->
<div class="grow h-0">
<div class="h-0 grow">
<ExtensionSlot
v-if="
bottomPanelStore.bottomPanelVisible &&

View File

@@ -1,6 +1,6 @@
<template>
<div class="h-full flex flex-col p-4">
<div class="flex-1 min-h-0 overflow-auto">
<div class="flex h-full flex-col p-4">
<div class="min-h-0 flex-1 overflow-auto">
<ShortcutsList
:commands="essentialsCommands"
:subcategories="essentialsSubcategories"

View File

@@ -1,13 +1,13 @@
<template>
<div class="shortcuts-list flex justify-center">
<div class="grid gap-4 md:gap-24 h-full grid-cols-1 md:grid-cols-3 w-[90%]">
<div class="grid h-full w-[90%] grid-cols-1 gap-4 md:grid-cols-3 md:gap-24">
<div
v-for="(subcategoryCommands, subcategory) in filteredSubcategories"
:key="subcategory"
class="flex flex-col"
>
<h3
class="subcategory-title text-xs font-bold uppercase tracking-wide text-surface-600 dark-theme:text-surface-400 mb-4"
class="subcategory-title mb-4 text-xs font-bold tracking-wide text-surface-600 uppercase dark-theme:text-surface-400"
>
{{ getSubcategoryTitle(subcategory) }}
</h3>
@@ -16,7 +16,7 @@
<div
v-for="command in subcategoryCommands"
:key="command.id"
class="shortcut-item flex justify-between items-center py-2 rounded hover:bg-surface-100 dark-theme:hover:bg-surface-700 transition-colors duration-200"
class="shortcut-item flex items-center justify-between rounded py-2 transition-colors duration-200 hover:bg-surface-100 dark-theme:hover:bg-surface-700"
>
<div class="shortcut-info grow pr-4">
<div class="shortcut-name text-sm font-medium">
@@ -32,7 +32,7 @@
<span
v-for="key in command.keybinding!.combo.getKeySequences()"
:key="key"
class="key-badge px-2 py-1 text-xs font-mono bg-surface-200 dark-theme:bg-surface-600 rounded border min-w-6 text-center"
class="key-badge min-w-6 rounded border bg-surface-200 px-2 py-1 text-center font-mono text-xs dark-theme:bg-surface-600"
>
{{ formatKey(key) }}
</span>

View File

@@ -1,6 +1,6 @@
<template>
<div class="h-full flex flex-col p-4">
<div class="flex-1 min-h-0 overflow-auto">
<div class="flex h-full flex-col p-4">
<div class="min-h-0 flex-1 overflow-auto">
<ShortcutsList
:commands="viewControlsCommands"
:subcategories="viewControlsSubcategories"

View File

@@ -1,10 +1,10 @@
<template>
<div
ref="rootEl"
class="relative overflow-hidden h-full w-full bg-neutral-900"
class="relative h-full w-full overflow-hidden bg-neutral-900"
>
<div class="p-terminal rounded-none h-full w-full p-2">
<div ref="terminalEl" class="h-full terminal-host" />
<div class="p-terminal h-full w-full rounded-none p-2">
<div ref="terminalEl" class="terminal-host h-full" />
</div>
<Button
v-tooltip.left="{

View File

@@ -1,11 +1,11 @@
<template>
<div class="bg-black h-full w-full">
<div class="h-full w-full bg-black">
<p v-if="errorMessage" class="p-4 text-center">
{{ errorMessage }}
</p>
<ProgressSpinner
v-else-if="loading"
class="relative inset-0 flex justify-center items-center h-full z-10"
class="relative inset-0 z-10 flex h-full items-center justify-center"
/>
<BaseTerminal v-show="!loading" @created="terminalCreated" />
</div>

View File

@@ -6,7 +6,7 @@
showDelay: 512
}"
href="#"
class="cursor-pointer p-breadcrumb-item-link"
class="p-breadcrumb-item-link cursor-pointer"
:class="{
'flex items-center gap-1': isActive,
'p-breadcrumb-item-link-menu-visible': menu?.overlayVisible,
@@ -37,7 +37,7 @@
v-if="isEditing"
ref="itemInputRef"
v-model="itemLabel"
class="fixed z-10000 text-[.8rem] px-2 py-2"
class="fixed z-10000 px-2 py-2 text-[.8rem]"
@blur="inputBlur(true)"
@click.stop
@keydown.enter="inputBlur(true)"

View File

@@ -14,7 +14,7 @@
unstyled
:pt="pt"
>
<div class="flex flex-col gap-2 p-2 min-w-40">
<div class="flex min-w-40 flex-col gap-2 p-2">
<slot :close="hide" />
</div>
</Popover>

View File

@@ -1,5 +1,5 @@
<template>
<div class="text-zinc-500 dark-theme:text-zinc-400 text-xs line-clamp-2 h-7">
<div class="line-clamp-2 h-7 text-xs text-zinc-500 dark-theme:text-zinc-400">
<slot></slot>
</div>
</template>

View File

@@ -1,31 +1,31 @@
<template>
<div :class="topStyle">
<slot class="absolute top-0 left-0 w-full h-full"></slot>
<slot class="absolute top-0 left-0 h-full w-full"></slot>
<div
v-if="slots['top-left']"
class="absolute top-2 left-2 flex gap-2 flex-wrap justify-start"
class="absolute top-2 left-2 flex flex-wrap justify-start gap-2"
>
<slot name="top-left"></slot>
</div>
<div
v-if="slots['top-right']"
class="absolute top-2 right-2 flex gap-2 flex-wrap justify-end"
class="absolute top-2 right-2 flex flex-wrap justify-end gap-2"
>
<slot name="top-right"></slot>
</div>
<div
v-if="slots['bottom-left']"
class="absolute bottom-2 left-2 flex gap-2 flex-wrap justify-start"
class="absolute bottom-2 left-2 flex flex-wrap justify-start gap-2"
>
<slot name="bottom-left"></slot>
</div>
<div
v-if="slots['bottom-right']"
class="absolute bottom-2 right-2 flex gap-2 flex-wrap justify-end"
class="absolute right-2 bottom-2 flex flex-wrap justify-end gap-2"
>
<slot name="bottom-right"></slot>
</div>

View File

@@ -1,6 +1,6 @@
<template>
<div
class="inline-flex justify-center items-center gap-1 shrink-0 py-1 px-2 text-xs bg-[#D9D9D966]/40 rounded font-bold text-white/90"
class="inline-flex shrink-0 items-center justify-center gap-1 rounded bg-[#D9D9D966]/40 px-2 py-1 text-xs font-bold text-white/90"
>
<slot name="icon" class="text-xs text-white/90"></slot>
<span>{{ label }}</span>

View File

@@ -11,7 +11,7 @@
icon="pi pi-exclamation-triangle"
size="small"
variant="outlined"
class="h-min my-2 px-1 max-w-xs"
class="my-2 h-min max-w-xs px-1"
:title="props.error"
:pt="{
text: { class: 'overflow-hidden text-ellipsis' }

View File

@@ -1,16 +1,16 @@
<template>
<div class="image-upload-wrapper">
<div class="flex gap-2 items-center">
<div class="flex items-center gap-2">
<div
class="preview-box border rounded p-2 w-16 h-16 flex items-center justify-center"
class="preview-box flex h-16 w-16 items-center justify-center rounded border p-2"
:class="{ 'bg-gray-100 dark-theme:bg-gray-800': !modelValue }"
>
<img
v-if="modelValue"
:src="modelValue"
class="max-w-full max-h-full object-contain"
class="max-h-full max-w-full object-contain"
/>
<i v-else class="pi pi-image text-gray-400 text-xl" />
<i v-else class="pi pi-image text-xl text-gray-400" />
</div>
<div class="flex flex-col gap-2">

View File

@@ -1,7 +1,7 @@
<template>
<div
ref="containerRef"
class="relative overflow-hidden w-full h-full flex items-center justify-center"
class="relative flex h-full w-full items-center justify-center overflow-hidden"
>
<Skeleton
v-if="!isImageLoaded"
@@ -22,7 +22,7 @@
/>
<div
v-if="hasError"
class="absolute inset-0 flex items-center justify-center bg-surface-50 dark-theme:bg-surface-800 text-muted"
class="absolute inset-0 flex items-center justify-center bg-surface-50 text-muted dark-theme:bg-surface-800"
>
<img
src="/assets/images/default-template.png"

View File

@@ -1,11 +1,11 @@
<template>
<div class="no-results-placeholder p-8 h-full" :class="props.class">
<div class="no-results-placeholder h-full p-8" :class="props.class">
<Card>
<template #content>
<div class="flex flex-col items-center">
<i :class="icon" style="font-size: 3rem; margin-bottom: 1rem" />
<h3>{{ title }}</h3>
<p :class="textClass" class="whitespace-pre-line text-center">
<p :class="textClass" class="text-center whitespace-pre-line">
{{ message }}
</p>
<Button

View File

@@ -28,7 +28,7 @@
</IconField>
<div
v-if="filters?.length"
class="search-filters pt-2 flex flex-wrap gap-2"
class="search-filters flex flex-wrap gap-2 pt-2"
>
<SearchFilterChip
v-for="filter in filters"

View File

@@ -1,7 +1,7 @@
<template>
<div class="system-stats">
<div class="mb-6">
<h2 class="text-2xl font-semibold mb-4">
<h2 class="mb-4 text-2xl font-semibold">
{{ $t('g.systemInfo') }}
</h2>
<div class="grid grid-cols-2 gap-2">
@@ -17,7 +17,7 @@
<Divider />
<div>
<h2 class="text-2xl font-semibold mb-4">
<h2 class="mb-4 text-2xl font-semibold">
{{ $t('g.devices') }}
</h2>
<TabView v-if="props.stats.devices.length > 1">

View File

@@ -2,7 +2,7 @@
<Tree
v-model:expanded-keys="expandedKeys"
v-model:selection-keys="selectionKeys"
class="tree-explorer py-0 px-2 2xl:px-4"
class="tree-explorer px-2 py-0 2xl:px-4"
:class="props.class"
:value="renderedRoot.children"
selection-mode="single"

View File

@@ -12,9 +12,9 @@
:class="{
'pi pi-spin pi-spinner text-neutral-400':
validationState === ValidationState.LOADING,
'pi pi-check text-green-500 cursor-pointer':
'pi pi-check cursor-pointer text-green-500':
validationState === ValidationState.VALID,
'pi pi-times text-red-500 cursor-pointer':
'pi pi-times cursor-pointer text-red-500':
validationState === ValidationState.INVALID
}"
@click="validateUrl(props.modelValue)"

View File

@@ -11,7 +11,7 @@
severity="secondary"
icon="pi pi-dollar"
rounded
class="text-amber-400 p-1"
class="p-1 text-amber-400"
/>
<div :class="textClass">{{ formattedBalance }}</div>
</div>

View File

@@ -36,7 +36,7 @@
</template>
<template #contentFilter>
<div class="relative px-6 pt-2 pb-4 flex gap-2 flex-wrap">
<div class="relative flex flex-wrap gap-2 px-6 pt-2 pb-4">
<!-- Model Filter -->
<MultiSelect
v-model="selectedModelObjects"
@@ -97,7 +97,7 @@
</div>
<div
v-if="!isLoading"
class="px-6 pt-4 pb-2 text-2xl font-semibold text-neutral"
class="text-neutral px-6 pt-4 pb-2 text-2xl font-semibold"
>
<span>
{{ pageTitle }}
@@ -109,10 +109,10 @@
<!-- No Results State (only show when loaded and no results) -->
<div
v-if="!isLoading && filteredTemplates.length === 0"
class="flex flex-col items-center justify-center h-64 text-neutral-500"
class="flex h-64 flex-col items-center justify-center text-neutral-500"
>
<i class="icon-[lucide--search] w-12 h-12 mb-4 opacity-50" />
<p class="text-lg mb-2">
<i class="mb-4 icon-[lucide--search] h-12 w-12 opacity-50" />
<p class="mb-2 text-lg">
{{ $t('templateWorkflows.noResults', 'No templates found') }}
</p>
<p class="text-sm">
@@ -128,7 +128,7 @@
<!-- Title -->
<span
v-if="isLoading"
class="inline-block h-8 w-48 bg-dialog-surface rounded animate-pulse"
class="inline-block h-8 w-48 animate-pulse rounded bg-dialog-surface"
></span>
<!-- Template Cards Grid -->
@@ -148,7 +148,7 @@
<CardTop ratio="landscape">
<template #default>
<div
class="w-full h-full bg-dialog-surface animate-pulse"
class="h-full w-full animate-pulse bg-dialog-surface"
></div>
</template>
</CardTop>
@@ -157,10 +157,10 @@
<CardBottom>
<div class="px-4 py-3">
<div
class="h-6 bg-dialog-surface rounded animate-pulse mb-2"
class="mb-2 h-6 animate-pulse rounded bg-dialog-surface"
></div>
<div
class="h-4 bg-dialog-surface rounded animate-pulse"
class="h-4 animate-pulse rounded bg-dialog-surface"
></div>
</div>
</CardBottom>
@@ -184,7 +184,7 @@
<template #default>
<!-- Template Thumbnail -->
<div
class="w-full h-full relative rounded-lg overflow-hidden"
class="relative h-full w-full overflow-hidden rounded-lg"
>
<template v-if="template.mediaType === 'audio'">
<AudioThumbnail :src="getBaseThumbnailSrc(template)" />
@@ -248,7 +248,7 @@
</template>
<ProgressSpinner
v-if="loadingTemplate === template.name"
class="absolute inset-0 z-10 w-12 h-12 m-auto"
class="absolute inset-0 z-10 m-auto h-12 w-12"
/>
</div>
</template>
@@ -267,7 +267,7 @@
<CardBottom>
<div class="flex flex-col gap-2 pt-3">
<h3
class="line-clamp-1 text-sm m-0"
class="m-0 line-clamp-1 text-sm"
:title="
getTemplateTitle(
template,
@@ -285,7 +285,7 @@
<div class="flex justify-between gap-2">
<div class="flex-1">
<p
class="line-clamp-2 text-sm text-muted m-0"
class="m-0 line-clamp-2 text-sm text-muted"
:title="getTemplateDescription(template)"
>
{{ getTemplateDescription(template) }}
@@ -323,7 +323,7 @@
<CardTop ratio="square">
<template #default>
<div
class="w-full h-full bg-dialog-surface animate-pulse"
class="h-full w-full animate-pulse bg-dialog-surface"
></div>
</template>
</CardTop>
@@ -332,10 +332,10 @@
<CardBottom>
<div class="px-4 py-3">
<div
class="h-6 bg-dialog-surface rounded animate-pulse mb-2"
class="mb-2 h-6 animate-pulse rounded bg-dialog-surface"
></div>
<div
class="h-4 bg-dialog-surface rounded animate-pulse"
class="h-4 animate-pulse rounded bg-dialog-surface"
></div>
</div>
</CardBottom>
@@ -348,7 +348,7 @@
<div
v-if="!isLoading && hasMoreTemplates"
ref="loadTrigger"
class="w-full h-4 flex justify-center items-center mt-4"
class="mt-4 flex h-4 w-full items-center justify-center"
>
<div v-if="isLoadingMore" class="text-sm text-muted">
{{ $t('templateWorkflows.loadingMore', 'Loading more...') }}

View File

@@ -1,16 +1,16 @@
<template>
<div class="flex flex-col gap-4 max-w-96 h-110 p-2">
<div class="text-2xl font-medium mb-2">
<div class="flex h-110 max-w-96 flex-col gap-4 p-2">
<div class="mb-2 text-2xl font-medium">
{{ t('apiNodesSignInDialog.title') }}
</div>
<div class="text-base mb-4">
<div class="mb-4 text-base">
{{ t('apiNodesSignInDialog.message') }}
</div>
<ApiNodesList :node-names="apiNodeNames" />
<div class="flex justify-between items-center">
<div class="flex items-center justify-between">
<Button :label="t('g.learnMore')" link @click="handleLearnMoreClick" />
<div class="flex gap-2">
<Button

View File

@@ -1,7 +1,7 @@
<template>
<section class="prompt-dialog-content flex flex-col gap-6 m-2 mt-4">
<section class="prompt-dialog-content m-2 mt-4 flex flex-col gap-6">
<span>{{ message }}</span>
<ul v-if="itemList?.length" class="pl-4 m-0 flex flex-col gap-2">
<ul v-if="itemList?.length" class="m-0 flex flex-col gap-2 pl-4">
<li v-for="item of itemList" :key="item">
{{ item }}
</li>
@@ -15,14 +15,14 @@
>
{{ hint }}
</Message>
<div class="flex gap-4 justify-end">
<div class="flex justify-end gap-4">
<div
v-if="type === 'overwriteBlueprint'"
class="flex gap-4 justify-start"
class="flex justify-start gap-4"
>
<Checkbox
v-model="doNotAskAgain"
class="flex gap-4 justify-start"
class="flex justify-start gap-4"
input-id="doNotAskAgain"
binary
/>

View File

@@ -13,7 +13,7 @@
<span class="font-bold">{{ error.extensionFile }}</span>
</template>
<div class="flex gap-2 justify-center">
<div class="flex justify-center gap-2">
<Button
v-show="!reportOpen"
text
@@ -29,12 +29,12 @@
</div>
<template v-if="reportOpen">
<Divider />
<ScrollPanel class="w-full h-[400px] max-w-[80vw]">
<pre class="whitespace-pre-wrap break-words">{{ reportContent }}</pre>
<ScrollPanel class="h-[400px] w-full max-w-[80vw]">
<pre class="break-words whitespace-pre-wrap">{{ reportContent }}</pre>
</ScrollPanel>
<Divider />
</template>
<div class="flex gap-4 justify-end">
<div class="flex justify-end gap-4">
<FindIssueButton
:error-message="error.exceptionMessage"
:repo-owner="repoOwner"

View File

@@ -16,7 +16,7 @@
}"
>
<template #option="slotProps">
<div class="flex align-items-center">
<div class="align-items-center flex">
<span class="node-type">{{ slotProps.option.label }}</span>
<span v-if="slotProps.option.hint" class="node-hint">{{
slotProps.option.hint

View File

@@ -3,7 +3,7 @@
v-if="hasMissingCoreNodes"
severity="info"
icon="pi pi-info-circle"
class="my-2 mx-2"
class="mx-2 my-2"
:pt="{
root: { class: 'flex-col' },
text: { class: 'flex-1' }

View File

@@ -5,7 +5,7 @@
:title="t('missingModelsDialog.missingModels')"
:message="t('missingModelsDialog.missingModelsMessage')"
/>
<div class="flex gap-1 mb-4">
<div class="mb-4 flex gap-1">
<Checkbox v-model="doNotAskAgain" binary input-id="doNotAskAgain" />
<label for="doNotAskAgain">{{
t('missingModelsDialog.doNotAskAgain')

View File

@@ -1,5 +1,5 @@
<template>
<div class="w-96 p-2 overflow-x-hidden">
<div class="w-96 overflow-x-hidden p-2">
<ApiKeyForm
v-if="showApiKeyForm"
@back="showApiKeyForm = false"
@@ -7,11 +7,11 @@
/>
<template v-else>
<!-- Header -->
<div class="flex flex-col gap-4 mb-8">
<h1 class="text-2xl font-medium leading-normal my-0">
<div class="mb-8 flex flex-col gap-4">
<h1 class="my-0 text-2xl leading-normal font-medium">
{{ isSignIn ? t('auth.login.title') : t('auth.signup.title') }}
</h1>
<p class="text-base my-0">
<p class="my-0 text-base">
<span class="text-muted">{{
isSignIn
? t('auth.login.newUser')
@@ -88,17 +88,17 @@
>
<img
src="/assets/images/comfy-logo-mono.svg"
class="w-5 h-5 mr-2"
class="mr-2 h-5 w-5"
alt="Comfy"
/>
{{ t('auth.login.useApiKey') }}
</Button>
<small class="text-muted text-center">
<small class="text-center text-muted">
{{ t('auth.apiKey.helpText') }}
<a
:href="`${COMFY_PLATFORM_BASE_URL}/login`"
target="_blank"
class="text-blue-500 cursor-pointer"
class="cursor-pointer text-blue-500"
>
{{ t('auth.apiKey.generateKey') }}
</a>
@@ -115,12 +115,12 @@
</div>
<!-- Terms & Contact -->
<p class="text-xs text-muted mt-8">
<p class="mt-8 text-xs text-muted">
{{ t('auth.login.termsText') }}
<a
href="https://www.comfy.org/terms-of-service"
target="_blank"
class="text-blue-500 cursor-pointer"
class="cursor-pointer text-blue-500"
>
{{ t('auth.login.termsLink') }}
</a>
@@ -128,12 +128,12 @@
<a
href="https://www.comfy.org/privacy"
target="_blank"
class="text-blue-500 cursor-pointer"
class="cursor-pointer text-blue-500"
>
{{ t('auth.login.privacyLink') }} </a
>.
{{ t('auth.login.questionsContactPrefix') }}
<a href="mailto:hello@comfy.org" class="text-blue-500 cursor-pointer">
<a href="mailto:hello@comfy.org" class="cursor-pointer text-blue-500">
hello@comfy.org</a
>.
</p>

View File

@@ -1,21 +1,21 @@
<template>
<div class="flex flex-col w-96 p-2 gap-10">
<div class="flex w-96 flex-col gap-10 p-2">
<div v-if="isInsufficientCredits" class="flex flex-col gap-4">
<h1 class="text-2xl font-medium leading-normal my-0">
<h1 class="my-0 text-2xl leading-normal font-medium">
{{ $t('credits.topUp.insufficientTitle') }}
</h1>
<p class="text-base my-0">
<p class="my-0 text-base">
{{ $t('credits.topUp.insufficientMessage') }}
</p>
</div>
<!-- Balance Section -->
<div class="flex justify-between items-center">
<div class="flex flex-col gap-2 w-full">
<div class="text-muted text-base">
<div class="flex items-center justify-between">
<div class="flex w-full flex-col gap-2">
<div class="text-base text-muted">
{{ $t('credits.yourCreditBalance') }}
</div>
<div class="flex items-center justify-between w-full">
<div class="flex w-full items-center justify-between">
<UserCredit text-class="text-2xl" />
<Button
outlined
@@ -30,7 +30,7 @@
<!-- Amount Input Section -->
<div class="flex flex-col gap-2">
<span class="text-muted text-sm"
<span class="text-sm text-muted"
>{{ $t('credits.topUp.quickPurchase') }}:</span
>
<div class="grid grid-cols-[2fr_1fr] gap-2">

View File

@@ -1,6 +1,6 @@
<template>
<Form
class="flex flex-col gap-6 w-96"
class="flex w-96 flex-col gap-6"
:resolver="zodResolver(updatePasswordSchema)"
@submit="onSubmit"
>
@@ -10,7 +10,7 @@
<Button
type="submit"
:label="$t('userSettings.updatePassword')"
class="h-10 font-medium mt-4"
class="mt-4 h-10 font-medium"
:loading="loading"
/>
</Form>

View File

@@ -4,7 +4,7 @@
severity="secondary"
icon="pi pi-dollar"
rounded
class="text-amber-400 p-1"
class="p-1 text-amber-400"
/>
<InputNumber
v-if="editable"
@@ -21,7 +21,7 @@
/>
<span v-else class="text-xl">{{ amount }}</span>
</div>
<ProgressSpinner v-if="loading" class="w-8 h-8" />
<ProgressSpinner v-if="loading" class="h-8 w-8" />
<Button
v-else
:severity="preselected ? 'primary' : 'secondary'"

View File

@@ -1,6 +1,6 @@
<template>
<PanelTemplate value="About" class="about-container">
<h2 class="text-2xl font-bold mb-2">
<h2 class="mb-2 text-2xl font-bold">
{{ $t('g.about') }}
</h2>
<div class="space-y-2">

View File

@@ -1,7 +1,7 @@
<template>
<TabPanel value="Credits" class="credits-container h-full">
<div class="flex flex-col h-full">
<h2 class="text-2xl font-bold mb-2">
<div class="flex h-full flex-col">
<h2 class="mb-2 text-2xl font-bold">
{{ $t('credits.credits') }}
</h2>
@@ -11,7 +11,7 @@
<h3 class="text-sm font-medium text-muted">
{{ $t('credits.yourCreditBalance') }}
</h3>
<div class="flex justify-between items-center">
<div class="flex items-center justify-between">
<UserCredit text-class="text-3xl font-bold" />
<Skeleton v-if="loading" width="2rem" height="2rem" />
<Button
@@ -41,7 +41,7 @@
</div>
</div>
<div class="flex justify-between items-center">
<div class="flex items-center justify-between">
<h3>{{ $t('credits.activity') }}</h3>
<Button
:label="$t('credits.invoiceHistory')"
@@ -66,7 +66,7 @@
<template #body="{ data }">
<div
:class="[
'text-base font-medium text-center',
'text-center text-base font-medium',
data.isPositive ? 'text-sky-500' : 'text-red-400'
]"
>

View File

@@ -51,10 +51,7 @@
class="max-w-64 2xl:max-w-full"
>
<template #body="slotProps">
<div
class="overflow-hidden text-ellipsis whitespace-nowrap"
:title="slotProps.data.id"
>
<div class="truncate" :title="slotProps.data.id">
{{ slotProps.data.label }}
</div>
</template>

View File

@@ -1,8 +1,8 @@
<template>
<TabPanel :value="props.value" class="h-full w-full" :class="props.class">
<div class="flex flex-col h-full w-full gap-2">
<div class="flex h-full w-full flex-col gap-2">
<slot name="header" />
<ScrollPanel class="grow h-0 pr-2">
<ScrollPanel class="h-0 grow pr-2">
<slot />
</ScrollPanel>
<slot name="footer" />

View File

@@ -30,7 +30,7 @@
<div class="event-details">
<!-- Credits Added -->
<template v-if="data.event_type === EventType.CREDIT_ADDED">
<div class="text-green-500 font-semibold">
<div class="font-semibold text-green-500">
{{ $t('credits.added') }} ${{
customerEventService.formatAmount(data.params?.amount)
}}

View File

@@ -1,7 +1,7 @@
<template>
<TabPanel value="User" class="user-settings-container h-full">
<div class="flex flex-col h-full">
<h2 class="text-2xl font-bold mb-2">{{ $t('userSettings.title') }}</h2>
<div class="flex h-full flex-col">
<h2 class="mb-2 text-2xl font-bold">{{ $t('userSettings.title') }}</h2>
<Divider class="mb-3" />
<!-- Normal User Panel -->
@@ -35,7 +35,7 @@
<h3 class="font-medium">
{{ $t('userSettings.provider') }}
</h3>
<div class="text-muted flex items-center gap-1">
<div class="flex items-center gap-1 text-muted">
<i :class="providerIcon" />
{{ providerName }}
<Button
@@ -54,7 +54,7 @@
<ProgressSpinner
v-if="loading"
class="w-8 h-8 mt-4"
class="mt-4 h-8 w-8"
style="--pc-spinner-color: #000"
/>
<div v-else class="mt-4 flex flex-col gap-2">

View File

@@ -1,17 +1,17 @@
<template>
<div class="flex flex-col gap-6">
<div class="flex flex-col gap-4 mb-8">
<h1 class="text-2xl font-medium leading-normal my-0">
<div class="mb-8 flex flex-col gap-4">
<h1 class="my-0 text-2xl leading-normal font-medium">
{{ t('auth.apiKey.title') }}
</h1>
<div class="flex flex-col gap-2">
<p class="text-base my-0 text-muted">
<p class="my-0 text-base text-muted">
{{ t('auth.apiKey.description') }}
</p>
<a
href="https://docs.comfy.org/interface/user#logging-in-with-an-api-key"
target="_blank"
class="text-blue-500 cursor-pointer"
class="cursor-pointer text-blue-500"
>
{{ t('g.learnMore') }}
</a>
@@ -30,7 +30,7 @@
<div class="flex flex-col gap-2">
<label
class="opacity-80 text-base font-medium mb-2"
class="mb-2 text-base font-medium opacity-80"
for="comfy-org-api-key"
>
{{ t('auth.apiKey.label') }}
@@ -50,7 +50,7 @@
<a
:href="`${COMFY_PLATFORM_BASE_URL}/login`"
target="_blank"
class="text-blue-500 cursor-pointer"
class="cursor-pointer text-blue-500"
>
{{ t('auth.apiKey.generateKey') }}
</a>
@@ -58,7 +58,7 @@
<a
href="https://docs.comfy.org/tutorials/api-nodes/overview#log-in-with-api-key-on-non-whitelisted-websites"
target="_blank"
class="text-blue-500 cursor-pointer"
class="cursor-pointer text-blue-500"
>
{{ t('auth.apiKey.whitelistInfo') }}
</a>
@@ -66,7 +66,7 @@
</div>
</div>
<div class="flex justify-between items-center mt-4">
<div class="mt-4 flex items-center justify-between">
<Button type="button" link @click="$emit('back')">
{{ t('g.back') }}
</Button>

View File

@@ -1,9 +1,9 @@
<template>
<!-- Password Field -->
<FormField v-slot="$field" name="password" class="flex flex-col gap-2">
<div class="flex justify-between items-center mb-2">
<div class="mb-2 flex items-center justify-between">
<label
class="opacity-80 text-base font-medium"
class="text-base font-medium opacity-80"
for="comfy-org-sign-up-password"
>
{{ t('auth.signup.passwordLabel') }}
@@ -68,7 +68,7 @@
<!-- Confirm Password Field -->
<FormField v-slot="$field" name="confirmPassword" class="flex flex-col gap-2">
<label
class="opacity-80 text-base font-medium mb-2"
class="mb-2 text-base font-medium opacity-80"
for="comfy-org-sign-up-confirm-password"
>
{{ t('auth.login.confirmPasswordLabel') }}

View File

@@ -7,7 +7,7 @@
>
<!-- Email Field -->
<div class="flex flex-col gap-2">
<label class="opacity-80 text-base font-medium mb-2" :for="emailInputId">
<label class="mb-2 text-base font-medium opacity-80" :for="emailInputId">
{{ t('auth.login.emailLabel') }}
</label>
<InputText
@@ -26,15 +26,15 @@
<!-- Password Field -->
<div class="flex flex-col gap-2">
<div class="flex justify-between items-center mb-2">
<div class="mb-2 flex items-center justify-between">
<label
class="opacity-80 text-base font-medium"
class="text-base font-medium opacity-80"
for="comfy-org-sign-in-password"
>
{{ t('auth.login.passwordLabel') }}
</label>
<span
class="text-muted text-base font-medium cursor-pointer select-none"
class="cursor-pointer text-base font-medium text-muted select-none"
:class="{
'text-link-disabled': !$form.email?.value || $form.email?.invalid
}"
@@ -60,12 +60,12 @@
</div>
<!-- Submit Button -->
<ProgressSpinner v-if="loading" class="w-8 h-8" />
<ProgressSpinner v-if="loading" class="h-8 w-8" />
<Button
v-else
type="submit"
:label="t('auth.login.loginButton')"
class="h-10 font-medium mt-4"
class="mt-4 h-10 font-medium"
/>
</Form>
</template>

View File

@@ -7,7 +7,7 @@
<!-- Email Field -->
<FormField v-slot="$field" name="email" class="flex flex-col gap-2">
<label
class="opacity-80 text-base font-medium mb-2"
class="mb-2 text-base font-medium opacity-80"
for="comfy-org-sign-up-email"
>
{{ t('auth.signup.emailLabel') }}
@@ -40,11 +40,11 @@
/>
<label
for="comfy-org-sign-up-personal-data-consent"
class="opacity-80 text-base font-medium"
class="text-base font-medium opacity-80"
>
{{ t('auth.signup.personalDataConsentLabel') }}
</label>
<small v-if="$field.error" class="text-red-500 -mt-4">{{
<small v-if="$field.error" class="-mt-4 text-red-500">{{
$field.error.message
}}</small>
</FormField>
@@ -53,7 +53,7 @@
<Button
type="submit"
:label="t('auth.signup.signUpButton')"
class="h-10 font-medium mt-4"
class="mt-4 h-10 font-medium"
/>
</Form>
</template>

View File

@@ -10,7 +10,7 @@
<BottomPanel />
</template>
<template #graph-canvas-panel>
<div class="absolute top-0 left-0 w-auto max-w-full pointer-events-auto">
<div class="pointer-events-auto absolute top-0 left-0 w-auto max-w-full">
<SecondRowWorkflowTabs
v-if="workflowTabsPosition === 'Topbar (2nd-row)'"
/>

View File

@@ -10,7 +10,7 @@
></div>
<ButtonGroup
class="p-buttongroup-vertical p-1 absolute bottom-4 right-2 md:right-4"
class="p-buttongroup-vertical absolute right-2 bottom-4 p-1 md:right-4"
:style="stringifiedMinimapStyles.buttonGroupStyles"
@wheel="canvasInteractions.handleWheel"
>
@@ -44,7 +44,7 @@
</Button>
<!-- vertical line with bg E1DED5 -->
<div class="w-px my-1 bg-[#E1DED5] dark-theme:bg-[#2E3037] mx-2" />
<div class="mx-2 my-1 w-px bg-[#E1DED5] dark-theme:bg-[#2E3037]" />
<Button
v-tooltip.top="fitViewTooltip"
@@ -52,7 +52,7 @@
icon="pi pi-expand"
:aria-label="fitViewTooltip"
:style="stringifiedMinimapStyles.buttonStyles"
class="dark-theme:hover:bg-[#444444]! hover:bg-[#E7E6E6]!"
class="hover:bg-[#E7E6E6]! dark-theme:hover:bg-[#444444]!"
@click="() => commandStore.execute('Comfy.Canvas.FitView')"
>
<template #icon>
@@ -77,7 +77,7 @@
</span>
</Button>
<div class="w-px my-1 bg-[#E1DED5] dark-theme:bg-[#2E3037] mx-2" />
<div class="mx-2 my-1 w-px bg-[#E1DED5] dark-theme:bg-[#2E3037]" />
<Button
ref="focusButton"

View File

@@ -2,12 +2,12 @@
<div
ref="toolboxRef"
style="transform: translate(var(--tb-x), var(--tb-y))"
class="fixed left-0 top-0 z-40 pointer-events-none"
class="pointer-events-none fixed top-0 left-0 z-40"
>
<Transition name="slide-up">
<Panel
v-if="visible"
class="rounded-lg selection-toolbox pointer-events-auto"
class="selection-toolbox pointer-events-auto rounded-lg"
:style="`backgroundColor: ${containerStyles.backgroundColor};`"
:pt="{
header: 'hidden',

View File

@@ -1,10 +1,10 @@
<template>
<div
v-if="visible"
class="w-[250px] absolute flex justify-center right-2 md:right-11 z-1300 bottom-[66px] bg-inherit! border-0!"
class="absolute right-2 bottom-[66px] z-1300 flex w-[250px] justify-center border-0! bg-inherit! md:right-11"
>
<div
class="bg-white dark-theme:bg-[#2b2b2b] border border-gray-200 dark-theme:border-gray-700 rounded-lg shadow-lg p-4 w-4/5"
class="w-4/5 rounded-lg border border-gray-200 bg-white p-4 shadow-lg dark-theme:border-gray-700 dark-theme:bg-[#2b2b2b]"
:style="filteredMinimapStyles"
@click.stop
>
@@ -26,10 +26,10 @@
@mouseleave="stopRepeat"
>
<template #default>
<span class="text-sm font-medium block">{{
<span class="block text-sm font-medium">{{
$t('graphCanvasMenu.zoomIn')
}}</span>
<span class="text-sm text-gray-500 block">{{
<span class="block text-sm text-gray-500">{{
zoomInCommandText
}}</span>
</template>
@@ -52,10 +52,10 @@
@mouseleave="stopRepeat"
>
<template #default>
<span class="text-sm font-medium block">{{
<span class="block text-sm font-medium">{{
$t('graphCanvasMenu.zoomOut')
}}</span>
<span class="text-sm text-gray-500 block">{{
<span class="block text-sm text-gray-500">{{
zoomOutCommandText
}}</span>
</template>
@@ -76,15 +76,15 @@
@click="executeCommand('Comfy.Canvas.FitView')"
>
<template #default>
<span class="text-sm font-medium block">{{
<span class="block text-sm font-medium">{{
$t('zoomControls.zoomToFit')
}}</span>
<span class="text-sm text-gray-500 block">{{
<span class="block text-sm text-gray-500">{{
zoomToFitCommandText
}}</span>
</template>
</Button>
<hr class="border-[#E1DED5] mb-1 dark-theme:border-[#2E3037]" />
<hr class="mb-1 border-[#E1DED5] dark-theme:border-[#2E3037]" />
<Button
severity="secondary"
text
@@ -101,18 +101,18 @@
@click="executeCommand('Comfy.Canvas.ToggleMinimap')"
>
<template #default>
<span class="text-sm font-medium block">{{
<span class="block text-sm font-medium">{{
minimapToggleText
}}</span>
<span class="text-sm text-gray-500 block">{{
<span class="block text-sm text-gray-500">{{
showMinimapCommandText
}}</span>
</template>
</Button>
<hr class="border-[#E1DED5] mt-1 dark-theme:border-[#2E3037]" />
<hr class="mt-1 border-[#E1DED5] dark-theme:border-[#2E3037]" />
<div
ref="zoomInputContainer"
class="flex items-center px-2 bg-[#E7E6E6] focus-within:bg-[#F3F3F3] dark-theme:bg-[#8282821A] rounded p-2 zoomInputContainer"
class="zoomInputContainer flex items-center rounded bg-[#E7E6E6] p-2 px-2 focus-within:bg-[#F3F3F3] dark-theme:bg-[#8282821A]"
>
<InputNumber
ref="zoomInput"
@@ -127,7 +127,7 @@
@input="applyZoom"
@keyup.enter="applyZoom"
/>
<span class="text-sm text-gray-500 -ml-4">%</span>
<span class="-ml-4 text-sm text-gray-500">%</span>
</div>
</div>
</div>

View File

@@ -7,11 +7,11 @@
severity="secondary"
text
data-testid="bypass-button"
class="hover:dark-theme:bg-charcoal-600 hover:bg-[#E7E6E6]"
class="hover:bg-[#E7E6E6] hover:dark-theme:bg-charcoal-600"
@click="toggleBypass"
>
<template #icon>
<i class="icon-[lucide--ban] w-4 h-4" />
<i class="icon-[lucide--ban] h-4 w-4" />
</template>
</Button>
</template>

View File

@@ -12,11 +12,11 @@
>
<div class="flex items-center gap-1 px-0">
<i
class="w-4 h-4 pi pi-circle-fill"
class="pi pi-circle-fill h-4 w-4"
:style="{ color: currentColor ?? '' }"
/>
<i
class="w-4 h-4 pi pi-chevron-down py-1"
class="pi pi-chevron-down h-4 w-4 py-1"
:style="{ fontSize: '0.5rem' }"
/>
</div>

View File

@@ -11,7 +11,7 @@
@click="() => commandStore.execute('Comfy.Graph.UnpackSubgraph')"
>
<template #icon>
<i class="icon-[lucide--expand] w-4 h-4" />
<i class="icon-[lucide--expand] h-4 w-4" />
</template>
</Button>
<Button

View File

@@ -4,13 +4,13 @@
value: t('selectionToolbox.executeButton.tooltip'),
showDelay: 1000
}"
class="dark-theme:bg-[#0B8CE9] bg-[#31B9F4] size-8 !p-0"
class="size-8 bg-[#31B9F4] !p-0 dark-theme:bg-[#0B8CE9]"
text
@mouseenter="() => handleMouseEnter()"
@mouseleave="() => handleMouseLeave()"
@click="handleClick"
>
<i class="icon-[lucide--play] text-white size-4" />
<i class="icon-[lucide--play] size-4 text-white" />
</Button>
</template>

View File

@@ -9,7 +9,7 @@
severity="secondary"
@click="frameNodes"
>
<i class="icon-[lucide--frame] w-4 h-4" />
<i class="icon-[lucide--frame] h-4 w-4" />
</Button>
</template>

View File

@@ -9,7 +9,7 @@
severity="secondary"
@click="toggleHelp"
>
<i class="icon-[lucide--info] w-4 h-4" />
<i class="icon-[lucide--info] h-4 w-4" />
</Button>
</template>

View File

@@ -9,7 +9,7 @@
text
@click="openMaskEditor"
>
<i-comfy:mask class="!w-4 !h-4" />
<i-comfy:mask class="!h-4 !w-4" />
</Button>
</template>

View File

@@ -1,15 +1,15 @@
<template>
<div
v-if="option.type === 'divider'"
class="h-px bg-gray-200 dark-theme:bg-zinc-700 my-1"
class="my-1 h-px bg-gray-200 dark-theme:bg-zinc-700"
/>
<div
v-else
role="button"
class="flex items-center gap-2 px-3 py-1.5 text-sm text-left hover:bg-gray-100 dark-theme:hover:bg-zinc-700 rounded cursor-pointer"
class="flex cursor-pointer items-center gap-2 rounded px-3 py-1.5 text-left text-sm hover:bg-gray-100 dark-theme:hover:bg-zinc-700"
@click="handleClick"
>
<i v-if="option.icon" :class="[option.icon, 'w-4 h-4']" />
<i v-if="option.icon" :class="[option.icon, 'h-4 w-4']" />
<span class="flex-1">{{ option.label }}</span>
<span v-if="option.shortcut" class="text-xs opacity-60">
{{ option.shortcut }}
@@ -24,11 +24,11 @@
:severity="option.badge === 'new' ? 'info' : 'secondary'"
:value="t(option.badge)"
:class="{
'bg-[#31B9F4] dark-theme:bg-[#0B8CE9] rounded-4xl':
'rounded-4xl bg-[#31B9F4] dark-theme:bg-[#0B8CE9]':
option.badge === 'new',
'bg-[#9C9EAB] dark-theme:bg-[#000] rounded-4xl':
'rounded-4xl bg-[#9C9EAB] dark-theme:bg-[#000]':
option.badge === 'deprecated',
'text-white uppercase text-[9px] h-4 px-1 gap-2.5': true
'h-4 gap-2.5 px-1 text-[9px] text-white uppercase': true
}"
/>
</div>

View File

@@ -13,7 +13,7 @@
@hide="onPopoverHide"
@wheel="canvasInteractions.forwardEventToCanvas"
>
<div class="flex flex-col p-2 min-w-48">
<div class="flex min-w-48 flex-col p-2">
<MenuOptionItem
v-for="(option, index) in menuOptions"
:key="option.label || `divider-${index}`"

View File

@@ -11,7 +11,7 @@
severity="secondary"
@click="handleClick"
>
<i class="icon-[lucide--more-vertical] w-4 h-4" />
<i class="icon-[lucide--more-vertical] h-4 w-4" />
</Button>
</template>

View File

@@ -7,7 +7,7 @@
data-testid="refresh-button"
@click="refreshSelected"
>
<i class="icon-[lucide--refresh-cw] w-4 h-4" />
<i class="icon-[lucide--refresh-cw] h-4 w-4" />
</Button>
</template>

View File

@@ -28,13 +28,13 @@
>
<div
v-if="subOption.color"
class="w-5 h-5 rounded-full border border-gray-300 dark-theme:border-zinc-600"
class="h-5 w-5 rounded-full border border-gray-300 dark-theme:border-zinc-600"
:style="{ backgroundColor: subOption.color }"
/>
<template v-else-if="!subOption.color">
<i
v-if="isShapeSelected(subOption)"
class="icon-[lucide--check] w-4 h-4 flex-shrink-0"
class="icon-[lucide--check] h-4 w-4 flex-shrink-0"
/>
<div v-else class="w-4 flex-shrink-0" />
<span>{{ subOption.label }}</span>

View File

@@ -1,3 +1,3 @@
<template>
<div class="h-6 w-px bg-gray-300/10 dark-theme:bg-gray-600/10 self-center" />
<div class="h-6 w-px self-center bg-gray-300/10 dark-theme:bg-gray-600/10" />
</template>

View File

@@ -1,24 +1,24 @@
<template>
<ScrollPanel
ref="scrollPanelRef"
class="w-full min-h-[400px] rounded-lg px-2 py-2 text-xs"
class="min-h-[400px] w-full rounded-lg px-2 py-2 text-xs"
:pt="{ content: { id: 'chat-scroll-content' } }"
>
<div v-for="(item, i) in parsedHistory" :key="i" class="mb-4">
<!-- Prompt (user, right) -->
<span
:class="{
'opacity-40 pointer-events-none': editIndex !== null && i > editIndex
'pointer-events-none opacity-40': editIndex !== null && i > editIndex
}"
>
<div class="flex justify-end mb-1">
<div class="mb-1 flex justify-end">
<div
class="bg-gray-300 dark-theme:bg-gray-800 rounded-xl px-4 py-1 max-w-[80%] text-right"
class="max-w-[80%] rounded-xl bg-gray-300 px-4 py-1 text-right dark-theme:bg-gray-800"
>
<div class="break-words text-[12px]">{{ item.prompt }}</div>
<div class="text-[12px] break-words">{{ item.prompt }}</div>
</div>
</div>
<div class="flex justify-end mb-2 mr-1">
<div class="mr-1 mb-2 flex justify-end">
<CopyButton :text="item.prompt" />
<Button
v-tooltip="
@@ -26,7 +26,7 @@
"
text
rounded
class="p-1! h-4! w-4! text-gray-400 hover:text-gray-600 hover:dark-theme:text-gray-200 transition"
class="h-4! w-4! p-1! text-gray-400 transition hover:text-gray-600 hover:dark-theme:text-gray-200"
pt:icon:class="text-xs!"
:icon="editIndex === i ? 'pi pi-times' : 'pi pi-pencil'"
:aria-label="
@@ -40,7 +40,7 @@
<ResponseBlurb
:text="item.response"
:class="{
'opacity-25 pointer-events-none': editIndex !== null && i >= editIndex
'pointer-events-none opacity-25': editIndex !== null && i >= editIndex
}"
>
<div v-html="nl2br(linkifyHtml(item.response))" />

View File

@@ -1,11 +1,11 @@
<template>
<div
class="relative w-full text-xs min-h-[28px] max-h-[200px] rounded-lg px-4 py-2 overflow-y-auto"
class="relative max-h-[200px] min-h-[28px] w-full overflow-y-auto rounded-lg px-4 py-2 text-xs"
>
<div class="flex items-center gap-2">
<div class="flex-1 break-all flex items-center gap-2">
<div class="flex flex-1 items-center gap-2 break-all">
<span v-html="formattedText"></span>
<Skeleton v-if="isParentNodeExecuting" class="flex-1! h-4!" />
<Skeleton v-if="isParentNodeExecuting" class="h-4! flex-1!" />
</div>
</div>
</div>

View File

@@ -5,7 +5,7 @@
"
text
rounded
class="p-1! h-4! w-6! text-gray-400 hover:text-gray-600 hover:dark-theme:text-gray-200 transition"
class="h-4! w-6! p-1! text-gray-400 transition hover:text-gray-600 hover:dark-theme:text-gray-200"
pt:icon:class="text-xs!"
:icon="copied ? 'pi pi-check' : 'pi pi-copy'"
:aria-label="

View File

@@ -1,13 +1,13 @@
<template>
<span>
<div class="flex justify-start mb-1">
<div class="rounded-xl px-4 py-1 max-w-[80%]">
<div class="break-words text-[12px]">
<div class="mb-1 flex justify-start">
<div class="max-w-[80%] rounded-xl px-4 py-1">
<div class="text-[12px] break-words">
<slot />
</div>
</div>
</div>
<div class="flex justify-start ml-1">
<div class="ml-1 flex justify-start">
<CopyButton :text="text" />
</div>
</span>

View File

@@ -24,7 +24,7 @@
v-if="showSearchBox || showSelectedCount || showClearButton"
#header
>
<div class="pt-2 pb-0 px-2 flex flex-col">
<div class="flex flex-col px-2 pt-2 pb-0">
<SearchBox
v-if="showSearchBox"
v-model="searchQuery"
@@ -39,7 +39,7 @@
>
<span
v-if="showSelectedCount"
class="text-sm text-neutral-400 dark-theme:text-zinc-500 px-1"
class="px-1 text-sm text-neutral-400 dark-theme:text-zinc-500"
>
{{
selectedCount > 0
@@ -67,7 +67,7 @@
</span>
<span
v-if="selectedCount > 0"
class="pointer-events-none absolute -right-2 -top-2 z-10 flex h-5 w-5 items-center justify-center rounded-full bg-blue-400 dark-theme:bg-blue-500 text-xs font-semibold text-white"
class="pointer-events-none absolute -top-2 -right-2 z-10 flex h-5 w-5 items-center justify-center rounded-full bg-blue-400 text-xs font-semibold text-white dark-theme:bg-blue-500"
>
{{ selectedCount }}
</span>
@@ -82,7 +82,7 @@
<template #option="slotProps">
<div class="flex items-center gap-2" :style="popoverStyle">
<div
class="flex h-4 w-4 p-0.5 shrink-0 items-center justify-center rounded transition-all duration-200"
class="flex h-4 w-4 shrink-0 items-center justify-center rounded p-0.5 transition-all duration-200"
:class="
slotProps.selected
? 'bg-blue-400 dark-theme:border-blue-500 dark-theme:bg-blue-500'
@@ -91,11 +91,11 @@
>
<i
v-if="slotProps.selected"
class="icon-[lucide--check] text-xs text-bold text-white"
class="text-bold icon-[lucide--check] text-xs text-white"
/>
</div>
<Button
class="border-none outline-none bg-transparent text-left"
class="border-none bg-transparent text-left outline-none"
unstyled
>{{ slotProps.option.name }}</Button
>

View File

@@ -44,7 +44,7 @@
<!-- Option row -->
<template #option="{ option, selected }">
<div
class="flex items-center justify-between gap-3 w-full"
class="flex w-full items-center justify-between gap-3"
:style="optionStyle"
>
<span class="truncate">{{ option.name }}</span>

View File

@@ -1,6 +1,6 @@
<template>
<div
class="relative w-full h-full"
class="relative h-full w-full"
@mouseenter="handleMouseEnter"
@mouseleave="handleMouseLeave"
>
@@ -59,14 +59,14 @@
/>
<div
v-if="enable3DViewer"
class="absolute top-12 right-2 z-20 pointer-events-auto"
class="pointer-events-auto absolute top-12 right-2 z-20"
>
<ViewerControls :node="node" />
</div>
<div
v-if="showRecordingControls"
class="absolute right-2 z-20 pointer-events-auto"
class="pointer-events-auto absolute right-2 z-20"
:class="{
'top-12': !enable3DViewer,
'top-24': enable3DViewer

View File

@@ -1,6 +1,6 @@
<template>
<div
class="relative w-full h-full"
class="relative h-full w-full"
@mouseenter="handleMouseEnter"
@mouseleave="handleMouseLeave"
>
@@ -34,7 +34,7 @@
@up-direction-change="listenUpDirectionChange"
@recording-status-change="listenRecordingStatusChange"
/>
<div class="absolute top-0 left-0 w-full h-full pointer-events-none">
<div class="pointer-events-none absolute top-0 left-0 h-full w-full">
<Load3DControls
:input-spec="inputSpec"
:background-color="backgroundColor"
@@ -69,7 +69,7 @@
</div>
<div
v-if="showRecordingControls"
class="absolute top-12 right-2 z-20 pointer-events-auto"
class="pointer-events-auto absolute top-12 right-2 z-20"
>
<RecordingControls
:node="node"

View File

@@ -1,11 +1,11 @@
<template>
<div
v-if="animations && animations.length > 0"
class="absolute top-0 left-0 w-full flex justify-center pt-2 gap-2 items-center pointer-events-auto z-10"
class="pointer-events-auto absolute top-0 left-0 z-10 flex w-full items-center justify-center gap-2 pt-2"
>
<Button class="p-button-rounded p-button-text" @click="togglePlay">
<i
:class="['pi', playing ? 'pi-pause' : 'pi-play', 'text-white text-lg']"
:class="['pi', playing ? 'pi-pause' : 'pi-play', 'text-lg text-white']"
/>
</Button>

View File

@@ -1,21 +1,21 @@
<template>
<div
class="absolute top-12 left-2 flex flex-col pointer-events-auto z-20 bg-gray-700/30 rounded-lg"
class="pointer-events-auto absolute top-12 left-2 z-20 flex flex-col rounded-lg bg-gray-700/30"
>
<div class="relative show-menu">
<div class="show-menu relative">
<Button class="p-button-rounded p-button-text" @click="toggleMenu">
<i class="pi pi-bars text-white text-lg" />
<i class="pi pi-bars text-lg text-white" />
</Button>
<div
v-show="isMenuOpen"
class="absolute left-12 top-0 bg-black/50 rounded-lg shadow-lg"
class="absolute top-0 left-12 rounded-lg bg-black/50 shadow-lg"
>
<div class="flex flex-col">
<Button
v-for="category in availableCategories"
:key="category"
class="p-button-text w-full flex items-center justify-start"
class="p-button-text flex w-full items-center justify-start"
:class="{ 'bg-gray-600': activeCategory === category }"
@click="selectCategory(category)"
>
@@ -26,7 +26,7 @@
</div>
</div>
<div v-show="activeCategory" class="bg-gray-700/30 rounded-lg">
<div v-show="activeCategory" class="rounded-lg bg-gray-700/30">
<SceneControls
v-if="activeCategory === 'scene'"
ref="sceneControlsRef"
@@ -81,7 +81,7 @@
:class="[
'pi',
showPreview ? 'pi-eye' : 'pi-eye-slash',
'text-white text-lg'
'text-lg text-white'
]"
/>
</Button>

View File

@@ -1,5 +1,5 @@
<template>
<div ref="container" class="w-full h-full relative comfy-load-3d">
<div ref="container" class="comfy-load-3d relative h-full w-full">
<LoadingOverlay ref="loadingOverlayRef" />
</div>
</template>

View File

@@ -6,18 +6,18 @@
@mouseenter="viewer.handleMouseEnter"
@mouseleave="viewer.handleMouseLeave"
>
<div ref="mainContentRef" class="flex-1 relative">
<div ref="mainContentRef" class="relative flex-1">
<div
ref="containerRef"
class="absolute w-full h-full comfy-load-3d-viewer"
class="comfy-load-3d-viewer absolute h-full w-full"
@resize="viewer.handleResize"
/>
</div>
<div class="w-72 flex flex-col">
<div class="flex w-72 flex-col">
<div class="flex-1 overflow-y-auto p-4">
<div class="space-y-2">
<div class="p-2 space-y-4">
<div class="space-y-4 p-2">
<SceneControls
v-model:background-color="viewer.backgroundColor.value"
v-model:show-grid="viewer.showGrid.value"
@@ -26,27 +26,27 @@
/>
</div>
<div class="p-2 space-y-4">
<div class="space-y-4 p-2">
<ModelControls
v-model:up-direction="viewer.upDirection.value"
v-model:material-mode="viewer.materialMode.value"
/>
</div>
<div class="p-2 space-y-4">
<div class="space-y-4 p-2">
<CameraControls
v-model:camera-type="viewer.cameraType.value"
v-model:fov="viewer.fov.value"
/>
</div>
<div class="p-2 space-y-4">
<div class="space-y-4 p-2">
<LightControls
v-model:light-intensity="viewer.lightIntensity.value"
/>
</div>
<div class="p-2 space-y-4">
<div class="space-y-4 p-2">
<ExportControls @export-model="viewer.exportModel" />
</div>
</div>

View File

@@ -2,11 +2,11 @@
<Transition name="fade">
<div
v-if="modelLoading"
class="absolute inset-0 bg-black/50 flex items-center justify-center z-50"
class="absolute inset-0 z-50 flex items-center justify-center bg-black/50"
>
<div class="flex flex-col items-center">
<div class="spinner" />
<div class="text-white mt-4 text-lg">
<div class="mt-4 text-lg text-white">
{{ loadingMessage }}
</div>
</div>

View File

@@ -6,19 +6,19 @@
value: t('load3d.switchCamera'),
showDelay: 300
}"
:class="['pi', getCameraIcon, 'text-white text-lg']"
:class="['pi', getCameraIcon, 'text-lg text-white']"
/>
</Button>
<div v-if="showFOVButton" class="relative show-fov">
<div v-if="showFOVButton" class="show-fov relative">
<Button class="p-button-rounded p-button-text" @click="toggleFOV">
<i
v-tooltip.right="{ value: t('load3d.fov'), showDelay: 300 }"
class="pi pi-expand text-white text-lg"
class="pi pi-expand text-lg text-white"
/>
</Button>
<div
v-show="showFOV"
class="absolute left-12 top-0 bg-black/50 p-4 rounded-lg shadow-lg"
class="absolute top-0 left-12 rounded-lg bg-black/50 p-4 shadow-lg"
style="width: 150px"
>
<Slider

View File

@@ -1,6 +1,6 @@
<template>
<div class="flex flex-col">
<div class="relative show-export-formats">
<div class="show-export-formats relative">
<Button
class="p-button-rounded p-button-text"
@click="toggleExportFormats"
@@ -10,12 +10,12 @@
value: t('load3d.exportModel'),
showDelay: 300
}"
class="pi pi-download text-white text-lg"
class="pi pi-download text-lg text-white"
/>
</Button>
<div
v-show="showExportFormats"
class="absolute left-12 top-0 bg-black/50 rounded-lg shadow-lg"
class="absolute top-0 left-12 rounded-lg bg-black/50 shadow-lg"
>
<div class="flex flex-col">
<Button

View File

@@ -1,6 +1,6 @@
<template>
<div class="flex flex-col">
<div v-if="showLightIntensityButton" class="relative show-light-intensity">
<div v-if="showLightIntensityButton" class="show-light-intensity relative">
<Button
class="p-button-rounded p-button-text"
@click="toggleLightIntensity"
@@ -10,12 +10,12 @@
value: t('load3d.lightIntensity'),
showDelay: 300
}"
class="pi pi-sun text-white text-lg"
class="pi pi-sun text-lg text-white"
/>
</Button>
<div
v-show="showLightIntensity"
class="absolute left-12 top-0 bg-black/50 p-4 rounded-lg shadow-lg"
class="absolute top-0 left-12 rounded-lg bg-black/50 p-4 shadow-lg"
style="width: 150px"
>
<Slider

View File

@@ -1,18 +1,18 @@
<template>
<div class="flex flex-col">
<div class="relative show-up-direction">
<div class="show-up-direction relative">
<Button class="p-button-rounded p-button-text" @click="toggleUpDirection">
<i
v-tooltip.right="{
value: t('load3d.upDirection'),
showDelay: 300
}"
class="pi pi-arrow-up text-white text-lg"
class="pi pi-arrow-up text-lg text-white"
/>
</Button>
<div
v-show="showUpDirection"
class="absolute left-12 top-0 bg-black/50 rounded-lg shadow-lg"
class="absolute top-0 left-12 rounded-lg bg-black/50 shadow-lg"
>
<div class="flex flex-col">
<Button
@@ -28,7 +28,7 @@
</div>
</div>
<div class="relative show-material-mode">
<div class="show-material-mode relative">
<Button
class="p-button-rounded p-button-text"
@click="toggleMaterialMode"
@@ -38,12 +38,12 @@
value: t('load3d.materialMode'),
showDelay: 300
}"
class="pi pi-box text-white text-lg"
class="pi pi-box text-lg text-white"
/>
</Button>
<div
v-show="showMaterialMode"
class="absolute left-12 top-0 bg-black/50 rounded-lg shadow-lg"
class="absolute top-0 left-12 rounded-lg bg-black/50 shadow-lg"
>
<div class="flex flex-col">
<Button
@@ -59,7 +59,7 @@
</div>
</div>
<div v-if="materialMode === 'lineart'" class="relative show-edge-threshold">
<div v-if="materialMode === 'lineart'" class="show-edge-threshold relative">
<Button
class="p-button-rounded p-button-text"
@click="toggleEdgeThreshold"
@@ -69,15 +69,15 @@
value: t('load3d.edgeThreshold'),
showDelay: 300
}"
class="pi pi-sliders-h text-white text-lg"
class="pi pi-sliders-h text-lg text-white"
/>
</Button>
<div
v-show="showEdgeThreshold"
class="absolute left-12 top-0 bg-black/50 p-4 rounded-lg shadow-lg"
class="absolute top-0 left-12 rounded-lg bg-black/50 p-4 shadow-lg"
style="width: 150px"
>
<label class="text-white text-xs mb-1 block"
<label class="mb-1 block text-xs text-white"
>{{ t('load3d.edgeThreshold') }}: {{ edgeThreshold }}°</label
>
<Slider

View File

@@ -1,5 +1,5 @@
<template>
<div class="relative bg-gray-700/30 rounded-lg">
<div class="relative rounded-lg bg-gray-700/30">
<div class="flex flex-col gap-2">
<Button
class="p-button-rounded p-button-text"
@@ -10,7 +10,7 @@
value: t('load3d.resizeNodeMatchOutput'),
showDelay: 300
}"
class="pi pi-window-maximize text-white text-lg"
class="pi pi-window-maximize text-lg text-white"
/>
</Button>
<Button
@@ -31,7 +31,7 @@
:class="[
'pi',
isRecording ? 'pi-circle-fill' : 'pi-video',
'text-white text-lg'
'text-lg text-white'
]"
/>
</Button>
@@ -46,7 +46,7 @@
value: t('load3d.exportRecording'),
showDelay: 300
}"
class="pi pi-download text-white text-lg"
class="pi pi-download text-lg text-white"
/>
</Button>
@@ -60,13 +60,13 @@
value: t('load3d.clearRecording'),
showDelay: 300
}"
class="pi pi-trash text-white text-lg"
class="pi pi-trash text-lg text-white"
/>
</Button>
<div
v-if="recordingDuration > 0 && !isRecording"
class="text-xs text-white text-center mt-1"
class="mt-1 text-center text-xs text-white"
>
{{ formatDuration(recordingDuration) }}
</div>

View File

@@ -7,7 +7,7 @@
>
<i
v-tooltip.right="{ value: t('load3d.showGrid'), showDelay: 300 }"
class="pi pi-table text-white text-lg"
class="pi pi-table text-lg text-white"
/>
</Button>
@@ -18,13 +18,13 @@
value: t('load3d.backgroundColor'),
showDelay: 300
}"
class="pi pi-palette text-white text-lg"
class="pi pi-palette text-lg text-white"
/>
<input
ref="colorPickerRef"
type="color"
:value="backgroundColor"
class="absolute opacity-0 w-0 h-0 p-0 m-0 pointer-events-none"
class="pointer-events-none absolute m-0 h-0 w-0 p-0 opacity-0"
@input="
updateBackgroundColor(($event.target as HTMLInputElement).value)
"
@@ -39,13 +39,13 @@
value: t('load3d.uploadBackgroundImage'),
showDelay: 300
}"
class="pi pi-image text-white text-lg"
class="pi pi-image text-lg text-white"
/>
<input
ref="imagePickerRef"
type="file"
accept="image/*"
class="absolute opacity-0 w-0 h-0 p-0 m-0 pointer-events-none"
class="pointer-events-none absolute m-0 h-0 w-0 p-0 opacity-0"
@change="uploadBackgroundImage"
/>
</Button>
@@ -61,7 +61,7 @@
value: t('load3d.removeBackgroundImage'),
showDelay: 300
}"
class="pi pi-times text-white text-lg"
class="pi pi-times text-lg text-white"
/>
</Button>
</div>

View File

@@ -1,5 +1,5 @@
<template>
<div class="relative bg-gray-700/30 rounded-lg">
<div class="relative rounded-lg bg-gray-700/30">
<div class="flex flex-col gap-2">
<Button class="p-button-rounded p-button-text" @click="openIn3DViewer">
<i
@@ -7,7 +7,7 @@
value: t('load3d.openIn3DViewer'),
showDelay: 300
}"
class="pi pi-expand text-white text-lg"
class="pi pi-expand text-lg text-white"
/>
</Button>
</div>

View File

@@ -6,7 +6,7 @@ https://github.com/Nuked88/ComfyUI-N-Sidebar/blob/7ae7da4a9761009fb6629bc04c6830
<div v-else class="_sb_node_preview">
<div class="_sb_table">
<div
class="node_header text-ellipsis mr-4"
class="node_header mr-4 text-ellipsis"
:title="nodeDef.display_name"
:style="{
backgroundColor: litegraphColors.NODE_DEFAULT_COLOR,

View File

@@ -1,10 +1,10 @@
<template>
<div
class="comfy-vue-node-search-container flex justify-center items-center w-full min-w-96"
class="comfy-vue-node-search-container flex w-full min-w-96 items-center justify-center"
>
<div
v-if="enableNodePreview"
class="comfy-vue-node-preview-container absolute left-[-350px] top-[50px]"
class="comfy-vue-node-preview-container absolute top-[50px] left-[-350px]"
>
<NodePreview
v-if="hoveredSuggestion"

View File

@@ -1,11 +1,11 @@
<template>
<div
class="option-container flex justify-between items-center px-2 py-0 cursor-pointer overflow-hidden w-full"
class="option-container flex w-full cursor-pointer items-center justify-between overflow-hidden px-2 py-0"
>
<div class="option-display-name font-semibold flex flex-col">
<div class="option-display-name flex flex-col font-semibold">
<div>
<span v-if="isBookmarked">
<i class="pi pi-bookmark-fill text-sm mr-1" />
<i class="pi pi-bookmark-fill mr-1 text-sm" />
</span>
<span v-html="highlightQuery(nodeDef.display_name, currentQuery)" />
<span>&nbsp;</span>
@@ -15,7 +15,7 @@
</div>
<div
v-if="showCategory"
class="option-category font-light text-sm text-muted overflow-hidden text-ellipsis whitespace-nowrap"
class="option-category truncate text-sm font-light text-muted"
>
{{ nodeDef.category.replaceAll('/', ' > ') }}
</div>

View File

@@ -25,7 +25,7 @@
</teleport>
<div
v-if="selectedTab"
class="sidebar-content-container h-full overflow-y-auto overflow-x-hidden"
class="sidebar-content-container h-full overflow-x-hidden overflow-y-auto"
>
<ExtensionSlot :extension="selectedTab" />
</div>

View File

@@ -1,18 +1,18 @@
<template>
<div
class="comfy-vue-side-bar-container flex flex-col h-full group/sidebar-tab"
class="comfy-vue-side-bar-container group/sidebar-tab flex h-full flex-col"
:class="props.class"
>
<div class="comfy-vue-side-bar-header">
<Toolbar class="border-x-0 border-t-0 rounded-none px-2 py-1 min-h-8">
<Toolbar class="min-h-8 rounded-none border-x-0 border-t-0 px-2 py-1">
<template #start>
<span class="text-xs 2xl:text-sm truncate" :title="props.title">
<span class="truncate text-xs 2xl:text-sm" :title="props.title">
{{ props.title.toUpperCase() }}
</span>
</template>
<template #end>
<div
class="flex flex-row motion-safe:w-0 motion-safe:opacity-0 motion-safe:group-hover/sidebar-tab:w-auto motion-safe:group-hover/sidebar-tab:opacity-100 motion-safe:group-focus-within/sidebar-tab:w-auto motion-safe:group-focus-within/sidebar-tab:opacity-100 touch:w-auto touch:opacity-100 transition-all duration-200"
class="touch:w-auto touch:opacity-100 flex flex-row transition-all duration-200 motion-safe:w-0 motion-safe:opacity-0 motion-safe:group-focus-within/sidebar-tab:w-auto motion-safe:group-focus-within/sidebar-tab:opacity-100 motion-safe:group-hover/sidebar-tab:w-auto motion-safe:group-hover/sidebar-tab:opacity-100"
>
<slot name="tool-buttons" />
</div>
@@ -21,7 +21,7 @@
<slot name="header" />
</div>
<!-- h-0 to force scrollpanel to grow -->
<ScrollPanel class="comfy-vue-side-bar-body grow h-0">
<ScrollPanel class="comfy-vue-side-bar-body h-0 grow">
<slot name="body" />
</ScrollPanel>
</div>

View File

@@ -5,7 +5,7 @@
</div>
<div v-if="['cancelled', 'error'].includes(download.status ?? '')">
<Chip
class="h-6 text-sm font-light bg-red-700 mt-2"
class="mt-2 h-6 bg-red-700 text-sm font-light"
removable
@remove="handleRemoveDownload"
>
@@ -30,7 +30,7 @@
<Button
v-if="download.status === 'in_progress'"
v-tooltip.top="t('electronFileDownload.pause')"
class="file-action-button w-[22px] h-[22px]"
class="file-action-button h-[22px] w-[22px]"
size="small"
rounded
icon="pi pi-pause"
@@ -40,7 +40,7 @@
<Button
v-if="download.status === 'paused'"
v-tooltip.top="t('electronFileDownload.resume')"
class="file-action-button w-[22px] h-[22px]"
class="file-action-button h-[22px] w-[22px]"
size="small"
rounded
icon="pi pi-play"
@@ -50,7 +50,7 @@
<Button
v-if="['in_progress', 'paused'].includes(download.status ?? '')"
v-tooltip.top="t('electronFileDownload.cancel')"
class="file-action-button w-[22px] h-[22px] p-red"
class="file-action-button p-red h-[22px] w-[22px]"
size="small"
rounded
severity="danger"

View File

@@ -1,6 +1,6 @@
<template>
<div v-if="inProgressDownloads.length > 0" class="mx-6 mb-4">
<div class="text-lg my-4">
<div class="my-4 text-lg">
{{ $t('electronFileDownload.inProgress') }}
</div>

View File

@@ -1,7 +1,7 @@
<template>
<div class="flex flex-col h-full bg-(--p-tree-background) overflow-auto">
<div class="flex h-full flex-col overflow-auto bg-(--p-tree-background)">
<div
class="px-3 py-2 flex items-center border-b border-(--p-divider-color)"
class="flex items-center border-b border-(--p-divider-color) px-3 py-2"
>
<Button
v-tooltip.bottom="$t('g.back')"
@@ -12,7 +12,7 @@
/>
<span class="ml-2 font-semibold">{{ node.display_name }}</span>
</div>
<div class="p-4 grow node-help-content w-full mx-auto">
<div class="node-help-content mx-auto w-full grow p-4">
<ProgressSpinner
v-if="isLoading"
class="m-auto"
@@ -25,7 +25,7 @@
v-html="renderedHelpHtml"
/>
<!-- Fallback: markdown not found or fetch error -->
<div v-else class="text-sm space-y-6 fallback-content">
<div v-else class="fallback-content space-y-6 text-sm">
<p v-if="node.description">
<strong>{{ $t('g.description') }}:</strong> {{ node.description }}
</p>

View File

@@ -1,13 +1,13 @@
<template>
<BaseThumbnail>
<div
class="w-full h-full flex items-center justify-center p-4"
class="flex h-full w-full items-center justify-center p-4"
:style="{
backgroundImage: 'url(/assets/images/default-template.png)',
backgroundRepeat: 'round'
}"
>
<audio controls class="w-full relative" :src="src" @click.stop />
<audio controls class="relative w-full" :src="src" @click.stop />
</div>
</BaseThumbnail>
</template>

View File

@@ -1,22 +1,22 @@
<template>
<div
class="relative w-full aspect-square rounded-t-lg overflow-hidden select-none"
class="relative aspect-square w-full overflow-hidden rounded-t-lg select-none"
>
<div
v-if="!error"
ref="contentRef"
class="w-full h-full transform-gpu transition-transform duration-1000 ease-out"
class="h-full w-full transform-gpu transition-transform duration-1000 ease-out"
:style="
isHovered ? { transform: `scale(${1 + hoverZoom / 100})` } : undefined
"
>
<slot />
</div>
<div v-else class="w-full h-full flex items-center justify-center">
<div v-else class="flex h-full w-full items-center justify-center">
<img
src="/assets/images/default-template.png"
draggable="false"
class="transform-gpu transition-transform duration-300 ease-out w-full h-full object-cover"
class="h-full w-full transform-gpu object-cover transition-transform duration-300 ease-out"
/>
</div>
</div>

View File

@@ -23,7 +23,7 @@
}"
/>
<div
class="absolute inset-y-0 w-0.5 bg-white/30 backdrop-blur-sm z-10 pointer-events-none"
class="pointer-events-none absolute inset-y-0 z-10 w-0.5 bg-white/30 backdrop-blur-sm"
:style="{
left: `${sliderPosition}%`
}"

View File

@@ -1,6 +1,6 @@
<template>
<BaseThumbnail :is-hovered="isHovered">
<div class="relative w-full h-full">
<div class="relative h-full w-full">
<div class="absolute inset-0">
<LazyImage
:src="baseImageSrc"

View File

@@ -1,8 +1,8 @@
<template>
<Toast group="reroute-migration">
<template #message>
<div class="flex flex-col items-start flex-auto">
<div class="font-medium text-lg my-4">
<div class="flex flex-auto flex-col items-start">
<div class="my-4 text-lg font-medium">
{{ t('toastMessages.migrateToLitegraphReroute') }}
</div>
<Button

View File

@@ -1,6 +1,6 @@
<template>
<div
class="comfyui-logo-wrapper p-1 flex justify-center items-center cursor-pointer rounded-md mr-2"
class="comfyui-logo-wrapper mr-2 flex cursor-pointer items-center justify-center rounded-md p-1"
:class="{
'comfyui-logo-menu-visible': menuRef?.visible
}"
@@ -59,11 +59,11 @@
/>
<span
v-if="item?.comfyCommand?.keybinding"
class="ml-auto border border-surface rounded text-muted text-xs text-nowrap p-1 keybinding-tag"
class="keybinding-tag ml-auto rounded border border-surface p-1 text-xs text-nowrap text-muted"
>
{{ item.comfyCommand.keybinding.combo.toString() }}
</span>
<i v-if="item.items" class="ml-auto pi pi-angle-right" />
<i v-if="item.items" class="pi pi-angle-right ml-auto" />
</a>
</template>
</TieredMenu>

View File

@@ -14,10 +14,10 @@
/>
<!-- User Details -->
<h3 class="text-lg font-semibold truncate my-0 mb-1">
<h3 class="my-0 mb-1 truncate text-lg font-semibold">
{{ userDisplayName || $t('g.user') }}
</h3>
<p v-if="userEmail" class="text-sm text-muted truncate my-0">
<p v-if="userEmail" class="my-0 truncate text-sm text-muted">
{{ userEmail }}
</p>
</div>
@@ -61,11 +61,11 @@
<Divider class="my-2" />
<div class="w-full flex flex-col gap-2 p-2">
<div class="text-muted text-sm">
<div class="flex w-full flex-col gap-2 p-2">
<div class="text-sm text-muted">
{{ $t('credits.yourCreditBalance') }}
</div>
<div class="flex justify-between items-center">
<div class="flex items-center justify-between">
<UserCredit text-class="text-2xl" />
<Button :label="$t('credits.topUp.topUp')" @click="handleTopUp" />
</div>

View File

@@ -2,7 +2,7 @@
<div>
<div
v-show="showTopMenu && workflowTabsPosition === 'Topbar'"
class="w-full flex content-end z-1001 h-[38px]"
class="z-1001 flex h-[38px] w-full content-end"
style="background: var(--border-color)"
>
<WorkflowTabs />
@@ -14,7 +14,7 @@
:class="{ dropzone: isDropZone, 'dropzone-active': isDroppable }"
>
<CommandMenubar />
<div class="grow min-w-0 app-drag h-full"></div>
<div class="app-drag h-full min-w-0 grow"></div>
<div
ref="menuRight"
class="comfyui-menu-right flex-shrink-1 overflow-auto"
@@ -26,7 +26,7 @@
<!-- Virtual top menu for native window (drag handle) -->
<div
v-show="isNativeWindow() && !showTopMenu"
class="fixed top-0 left-0 app-drag w-full h-(--comfy-topbar-height)"
class="app-drag fixed top-0 left-0 h-(--comfy-topbar-height) w-full"
/>
</div>
</template>

View File

@@ -1,23 +1,23 @@
<template>
<div
ref="workflowTabRef"
class="flex p-2 gap-2 workflow-tab group"
class="workflow-tab group flex gap-2 p-2"
v-bind="$attrs"
@mouseenter="handleMouseEnter"
@mouseleave="handleMouseLeave"
@click="handleClick"
>
<span class="workflow-label text-sm max-w-[150px] truncate inline-block">
<span class="workflow-label inline-block max-w-[150px] truncate text-sm">
{{ workflowOption.workflow.filename }}
</span>
<div class="relative">
<span
v-if="shouldShowStatusIndicator"
class="group-hover:hidden absolute font-bold text-2xl top-1/2 left-1/2 -translate-1/2 z-10 bg-(--comfy-menu-bg) w-4"
class="absolute top-1/2 left-1/2 z-10 w-4 -translate-1/2 bg-(--comfy-menu-bg) text-2xl font-bold group-hover:hidden"
></span
>
<Button
class="close-button p-0 w-auto invisible"
class="close-button invisible w-auto p-0"
icon="pi pi-times"
text
severity="secondary"

Some files were not shown because too many files have changed in this diff Show More