style: apply Tailwind CSS class sorting across codebase

Co-authored-by: Amp <amp@ampcode.com>
Amp-Thread-ID: https://ampcode.com/threads/T-019bd8c8-bce1-70bc-a125-baf2a1503ee8
This commit is contained in:
Alexander Brown
2026-01-19 16:19:18 -08:00
parent 0bbb2d73e1
commit e7ce294aeb
168 changed files with 1777 additions and 1103 deletions

View File

@@ -226,8 +226,8 @@ In this project, only the `<i class="icon-[lucide--folder]" />` syntax from unpl
<script setup lang="ts"></script>
<template>
<i class="icon-[lucide--trophy] text-neutral size-4" />
<i class="icon-[lucide--settings] text-neutral size-4" />
<i class="text-neutral icon-[lucide--trophy] size-4" />
<i class="text-neutral icon-[lucide--settings] size-4" />
</template>
```

View File

@@ -1,24 +0,0 @@
import path from 'node:path'
export default {
'tests-ui/**': () =>
'echo "Files in tests-ui/ are deprecated. Colocate tests with source files." && exit 1',
'./**/*.js': (stagedFiles) => formatAndEslint(stagedFiles),
'./**/*.{ts,tsx,vue,mts}': (stagedFiles) => [
...formatAndEslint(stagedFiles),
'pnpm typecheck'
]
}
function formatAndEslint(fileNames) {
// Convert absolute paths to relative paths for better ESLint resolution
const relativePaths = fileNames.map((f) => path.relative(process.cwd(), f))
const joinedPaths = relativePaths.map((p) => `"${p}"`).join(' ')
return [
`pnpm exec oxfmt ${joinedPaths}`,
`pnpm exec oxlint --fix ${joinedPaths}`,
`pnpm exec eslint --cache --fix --no-warn-ignored ${joinedPaths}`
]
}

View File

@@ -1,6 +1,9 @@
import path from 'node:path'
export default {
'tests-ui/**': () =>
'echo "Files in tests-ui/ are deprecated. Colocate tests with source files." && exit 1',
'./**/*.js': (stagedFiles: string[]) => formatAndEslint(stagedFiles),
'./**/*.{ts,tsx,vue,mts}': (stagedFiles: string[]) => [
@@ -14,7 +17,7 @@ function formatAndEslint(fileNames: string[]) {
const relativePaths = fileNames.map((f) => path.relative(process.cwd(), f))
const joinedPaths = relativePaths.map((p) => `"${p}"`).join(' ')
return [
`pnpm exec prettier --cache --write ${joinedPaths}`,
`pnpm exec oxfmt ${joinedPaths}`,
`pnpm exec oxlint --fix ${joinedPaths}`,
`pnpm exec eslint --cache --fix --no-warn-ignored ${joinedPaths}`
]

View File

@@ -1,6 +1,6 @@
<template>
<div
class="w-full h-full absolute top-0 left-0 z-999 pointer-events-none flex flex-col"
class="pointer-events-none absolute top-0 left-0 z-999 flex h-full w-full flex-col"
>
<slot name="workflow-tabs" />
@@ -17,7 +17,7 @@
<Splitter
:key="splitterRefreshKey"
class="bg-transparent pointer-events-none border-none flex-1 overflow-hidden"
class="pointer-events-none flex-1 overflow-hidden border-none bg-transparent"
:state-key="sidebarStateKey"
state-storage="local"
@resizestart="onResizestart"
@@ -30,10 +30,10 @@
:class="
sidebarLocation === 'left'
? cn(
'side-bar-panel bg-comfy-menu-bg pointer-events-auto',
'side-bar-panel pointer-events-auto bg-comfy-menu-bg',
sidebarPanelVisible && 'min-w-78'
)
: 'bg-comfy-menu-bg pointer-events-auto'
: 'pointer-events-auto bg-comfy-menu-bg'
"
:min-size="sidebarLocation === 'left' ? 10 : 15"
:size="20"
@@ -54,11 +54,17 @@
</SplitterPanel>
<!-- Main panel (always present) -->
<SplitterPanel :size="80" class="flex flex-col">
<slot name="topmenu" :sidebar-panel-visible />
<SplitterPanel
:size="80"
class="flex flex-col"
>
<slot
name="topmenu"
:sidebar-panel-visible
/>
<Splitter
class="bg-transparent pointer-events-none border-none splitter-overlay-bottom mr-1 mb-1 ml-1 flex-1"
class="splitter-overlay-bottom pointer-events-none mr-1 mb-1 ml-1 flex-1 border-none bg-transparent"
layout="vertical"
:pt:gutter="
cn(
@@ -75,7 +81,7 @@
</SplitterPanel>
<SplitterPanel
v-show="bottomPanelVisible && !focusMode"
class="bottom-panel border border-(--p-panel-border-color) max-w-full overflow-x-auto bg-comfy-menu-bg pointer-events-auto rounded-lg"
class="bottom-panel pointer-events-auto max-w-full overflow-x-auto rounded-lg border border-(--p-panel-border-color) bg-comfy-menu-bg"
>
<slot name="bottom-panel" />
</SplitterPanel>
@@ -90,10 +96,10 @@
:class="
sidebarLocation === 'right'
? cn(
'side-bar-panel bg-comfy-menu-bg pointer-events-auto',
'side-bar-panel pointer-events-auto bg-comfy-menu-bg',
sidebarPanelVisible && 'min-w-78'
)
: 'bg-comfy-menu-bg pointer-events-auto'
: 'pointer-events-auto bg-comfy-menu-bg'
"
:min-size="sidebarLocation === 'right' ? 10 : 15"
:size="20"
@@ -103,7 +109,10 @@
sidebarLocation === 'right' ? t('sideToolbar.sidebar') : undefined
"
>
<slot v-if="sidebarLocation === 'left'" name="right-side-panel" />
<slot
v-if="sidebarLocation === 'left'"
name="right-side-panel"
/>
<slot
v-else-if="sidebarLocation === 'right' && sidebarPanelVisible"
name="side-bar-panel"

View File

@@ -1,7 +1,7 @@
<template>
<div
v-show="workspaceState.focusMode"
class="fixed z-9999 flex flex-row no-drag top-0 right-0"
class="no-drag fixed top-0 right-0 z-9999 flex flex-row"
>
<Button
v-tooltip="{ value: $t('menu.showMenu'), showDelay: 300 }"

View File

@@ -32,14 +32,14 @@
</div>
<div
class="actionbar-container pointer-events-auto flex gap-2 h-12 items-center rounded-lg border border-interface-stroke bg-comfy-menu-bg px-2 shadow-interface"
class="actionbar-container pointer-events-auto flex h-12 items-center gap-2 rounded-lg border border-interface-stroke bg-comfy-menu-bg px-2 shadow-interface"
>
<ActionBarButtons />
<!-- Support for legacy topbar elements attached by custom scripts, hidden if no elements present -->
<div
ref="legacyCommandsContainerRef"
class="[&:not(:has(*>*:not(:empty)))]:hidden"
></div>
/>
<ComfyActionbar />
<Button
v-tooltip.bottom="queueHistoryTooltipConfig"
@@ -54,7 +54,7 @@
<i class="icon-[lucide--history] size-4" />
<span
v-if="queuedCount > 0"
class="absolute -top-1 -right-1 min-w-[16px] rounded-full bg-primary-background py-0.25 text-[10px] font-medium leading-[14px] text-base-foreground"
class="absolute -top-1 -right-1 min-w-[16px] rounded-full bg-primary-background py-0.25 text-[10px] leading-[14px] font-medium text-base-foreground"
>
{{ queuedCount }}
</span>

View File

@@ -1,5 +1,8 @@
<template>
<div class="flex h-full items-center" :class="cn(!isDocked && '-ml-2')">
<div
class="flex h-full items-center"
:class="cn(!isDocked && '-ml-2')"
>
<div
v-if="isDragging && !isDocked"
:class="actionbarClass"
@@ -18,12 +21,15 @@
content: { class: isDocked ? 'p-0' : 'p-1' }
}"
>
<div ref="panelRef" class="flex items-center select-none gap-2">
<div
ref="panelRef"
class="flex items-center gap-2 select-none"
>
<span
ref="dragHandleRef"
:class="
cn(
'drag-handle cursor-grab w-3 h-max',
'drag-handle h-max w-3 cursor-grab',
isDragging && 'cursor-grabbing'
)
"
@@ -282,18 +288,18 @@ const actionbarClass = computed(() =>
cn(
'w-[200px] border-dashed border-blue-500 opacity-80',
'm-1.5 flex items-center justify-center self-stretch',
'rounded-md before:w-50 before:-ml-50 before:h-full',
'rounded-md before:-ml-50 before:h-full before:w-50',
'pointer-events-auto',
isMouseOverDropZone.value &&
'border-[3px] opacity-100 scale-105 shadow-[0_0_20px] shadow-blue-500'
'scale-105 border-[3px] opacity-100 shadow-[0_0_20px] shadow-blue-500'
)
)
const panelClass = computed(() =>
cn(
'actionbar pointer-events-auto z-1300',
isDragging.value && 'select-none pointer-events-none',
isDragging.value && 'pointer-events-none select-none',
isDocked.value
? 'p-0 static border-none bg-transparent'
? 'static border-none bg-transparent p-0'
: 'fixed shadow-interface'
)
)

View File

@@ -4,7 +4,10 @@
class="relative h-full w-full overflow-hidden bg-neutral-900"
>
<div class="p-terminal h-full w-full rounded-none p-2">
<div ref="terminalEl" class="terminal-host h-full" />
<div
ref="terminalEl"
class="terminal-host h-full"
/>
</div>
<Button
v-tooltip.left="{
@@ -15,7 +18,7 @@
size="sm"
:class="
cn('absolute top-2 right-8 transition-opacity', {
'opacity-0 pointer-events-none select-none': !isHovered
'pointer-events-none opacity-0 select-none': !isHovered
})
"
:aria-label="tooltipText"
@@ -109,6 +112,6 @@ onUnmounted(() => {
}
:deep(.p-terminal) .xterm-screen {
@apply bg-neutral-900 overflow-hidden;
@apply overflow-hidden bg-neutral-900;
}
</style>

View File

@@ -46,9 +46,9 @@
:is-active="item.key === activeItemKey"
/>
</template>
<template #separator
><span style="transform: scale(1.5)"> / </span></template
>
<template #separator>
<span style="transform: scale(1.5)"> / </span>
</template>
</Breadcrumb>
</div>
</template>
@@ -233,7 +233,7 @@ onUpdated(() => {
}
:deep(.p-breadcrumb-item) {
@apply flex items-center overflow-hidden h-8;
@apply flex h-8 items-center overflow-hidden;
min-width: calc(var(--p-breadcrumb-item-min-width) + 1rem);
border: 1px solid transparent;
background-color: transparent;

View File

@@ -21,8 +21,15 @@
class="icon-[lucide--triangle-alert] text-warning-background"
/>
<span class="p-breadcrumb-item-label px-2">{{ item.label }}</span>
<Tag v-if="item.isBlueprint" value="Blueprint" severity="primary" />
<i v-if="isActive" class="pi pi-angle-down text-[10px]"></i>
<Tag
v-if="item.isBlueprint"
value="Blueprint"
severity="primary"
/>
<i
v-if="isActive"
class="pi pi-angle-down text-[10px]"
/>
</a>
<Menu
v-if="isActive || isRoot"
@@ -208,7 +215,7 @@ defineExpose({
}
.p-breadcrumb-item-label {
@apply whitespace-nowrap text-ellipsis overflow-hidden;
@apply overflow-hidden text-ellipsis whitespace-nowrap;
}
.active-breadcrumb-item {

View File

@@ -2,12 +2,12 @@
<div
:class="
cn(
'flex justify-center items-center shrink-0 outline-hidden border-none p-0 rounded-lg shadow-sm transition-all duration-200 cursor-pointer bg-secondary-background',
'flex shrink-0 cursor-pointer items-center justify-center rounded-lg border-none bg-secondary-background p-0 shadow-sm outline-hidden transition-all duration-200',
backgroundClass
)
"
>
<slot></slot>
<slot />
</div>
</template>

View File

@@ -1,6 +1,6 @@
<template>
<div :class="containerClasses">
<slot></slot>
<slot />
</div>
</template>
@@ -14,6 +14,6 @@ const { fullHeight = true } = defineProps<{
}>()
const containerClasses = computed(() =>
cn('flex-1 w-full', fullHeight && 'h-full')
cn('w-full flex-1', fullHeight && 'h-full')
)
</script>

View File

@@ -1,7 +1,7 @@
<template>
<div :class="containerClasses">
<slot name="top"></slot>
<slot name="bottom"></slot>
<slot name="top" />
<slot name="bottom" />
</div>
</template>
@@ -59,7 +59,7 @@ const containerClasses = computed(() => {
outline: cn(
hasBorder && 'border-2 border-border-subtle',
hasCursor && 'cursor-pointer',
'hover:border-border-subtle/50 transition-colors'
'transition-colors hover:border-border-subtle/50'
)
}

View File

@@ -1,6 +1,6 @@
<template>
<div :class="chipClasses">
<slot name="icon"></slot>
<slot name="icon" />
<span>{{ label }}</span>
</div>
</template>
@@ -19,9 +19,9 @@ const baseClasses =
const variantStyles = {
dark: 'bg-zinc-500/40 text-white/90',
light: cn('backdrop-blur-[2px] bg-base-background/50 text-base-foreground'),
light: cn('bg-base-background/50 text-base-foreground backdrop-blur-[2px]'),
gray: cn(
'backdrop-blur-[2px] bg-modal-card-tag-background text-base-foreground'
'bg-modal-card-tag-background text-base-foreground backdrop-blur-[2px]'
)
}

View File

@@ -1,11 +1,14 @@
<template>
<span class="relative inline-flex items-center justify-center size-[1em]">
<i :class="mainIcon" class="text-[1em]" />
<span class="relative inline-flex size-[1em] items-center justify-center">
<i
:class="mainIcon"
class="text-[1em]"
/>
<i
:class="
cn(
subIcon,
'absolute leading-none pointer-events-none',
'pointer-events-none absolute leading-none',
positionX === 'left' ? 'left-0' : 'right-0',
positionY === 'top' ? 'top-0' : 'bottom-0'
)

View File

@@ -2,7 +2,7 @@
<div
:class="
cn(
'relative flex w-full items-center gap-2 bg-comfy-input cursor-text text-comfy-input-foreground',
'relative flex w-full cursor-text items-center gap-2 bg-comfy-input text-comfy-input-foreground',
customClass,
wrapperStyle
)
@@ -14,19 +14,22 @@
:placeholder
:autofocus
unstyled
class="absolute inset-0 size-full pl-11 border-none outline-none bg-transparent text-sm"
class="absolute inset-0 size-full border-none bg-transparent pl-11 text-sm outline-none"
:aria-label="placeholder"
/>
<Button
v-if="filterIcon"
size="icon"
variant="textonly"
class="filter-button absolute right-0 inset-y-0 m-0 p-0"
class="filter-button absolute inset-y-0 right-0 m-0 p-0"
@click="$emit('showFilter', $event)"
>
<i :class="filterIcon" />
</Button>
<InputIcon v-if="!modelValue" :class="icon" />
<InputIcon
v-if="!modelValue"
:class="icon"
/>
<Button
v-if="modelValue"
class="clear-button absolute left-0"
@@ -37,7 +40,10 @@
<i class="icon-[lucide--x] size-4" />
</Button>
</div>
<div v-if="filters?.length" class="search-filters flex flex-wrap gap-2 pt-2">
<div
v-if="filters?.length"
class="search-filters flex flex-wrap gap-2 pt-2"
>
<SearchFilterChip
v-for="filter in filters"
:key="filter.id"
@@ -109,7 +115,7 @@ watchDebounced(
const wrapperStyle = computed(() => {
if (showBorder) {
return cn('rounded p-2 border border-solid border-border-default')
return cn('rounded border border-solid border-border-default p-2')
}
// Size-specific classes matching button sizes for consistency

View File

@@ -2,7 +2,7 @@
<Tree
v-model:expanded-keys="expandedKeys"
v-model:selection-keys="selectionKeys"
class="tree-explorer px-2 py-0 2xl:px-4 bg-transparent"
class="tree-explorer bg-transparent px-2 py-0 2xl:px-4"
:class="props.class"
:value="renderedRoot.children"
selection-mode="single"
@@ -23,17 +23,26 @@
}"
>
<template #folder="{ node }">
<slot name="folder" :node="node">
<slot
name="folder"
:node="node"
>
<TreeExplorerTreeNode :node="node" />
</slot>
</template>
<template #node="{ node }">
<slot name="node" :node="node">
<slot
name="node"
:node="node"
>
<TreeExplorerTreeNode :node="node" />
</slot>
</template>
</Tree>
<ContextMenu ref="menu" :model="menuItems" />
<ContextMenu
ref="menu"
:model="menuItems"
/>
</template>
<script setup lang="ts">
import ContextMenu from 'primevue/contextmenu'

View File

@@ -12,13 +12,19 @@
>
<div class="node-content">
<span class="node-label">
<slot name="before-label" :node="props.node" />
<slot
name="before-label"
:node="props.node"
/>
<EditableText
:model-value="node.label"
:is-editing="isEditing"
@edit="handleRename"
/>
<slot name="after-label" :node="props.node" />
<slot
name="after-label"
:node="props.node"
/>
</span>
<Badge
v-if="showNodeBadgeText"
@@ -28,9 +34,12 @@
/>
</div>
<div
class="node-actions touch:opacity-100 motion-safe:opacity-0 motion-safe:group-hover/tree-node:opacity-100"
class="node-actions motion-safe:opacity-0 motion-safe:group-hover/tree-node:opacity-100 touch:opacity-100"
>
<slot name="actions" :node="props.node" />
<slot
name="actions"
:node="props.node"
/>
</div>
</div>
</template>

View File

@@ -1,6 +1,6 @@
<template>
<div
class="flex flex-col px-4 py-2 text-sm text-muted-foreground border-t border-border-default"
class="flex flex-col border-t border-border-default px-4 py-2 text-sm text-muted-foreground"
>
<p v-if="promptTextReal">
{{ promptTextReal }}

View File

@@ -1,6 +1,11 @@
<template>
<section class="w-full flex gap-2 justify-end px-2 pb-2">
<Button :disabled variant="textonly" autofocus @click="$emit('cancel')">
<section class="flex w-full justify-end gap-2 px-2 pb-2">
<Button
:disabled
variant="textonly"
autofocus
@click="$emit('cancel')"
>
{{ cancelTextX }}
</Button>
<Button

View File

@@ -1,8 +1,11 @@
<template>
<div
class="flex items-center gap-2 p-4 font-bold text-sm text-base-foreground font-inter"
class="flex items-center gap-2 p-4 font-inter text-sm font-bold text-base-foreground"
>
<span v-if="title" class="flex-auto">{{ title }}</span>
<span
v-if="title"
class="flex-auto"
>{{ title }}</span>
</div>
</template>
<script setup lang="ts">

View File

@@ -14,21 +14,27 @@
}}
</p>
</div>
<MissingCoreNodesMessage v-if="!isCloud" :missing-core-nodes />
<MissingCoreNodesMessage
v-if="!isCloud"
:missing-core-nodes
/>
<!-- Missing Nodes List Wrapper -->
<div
class="comfy-missing-nodes flex flex-col max-h-[256px] rounded-lg py-2 scrollbar-custom bg-secondary-background"
class="comfy-missing-nodes flex scrollbar-custom max-h-[256px] flex-col rounded-lg bg-secondary-background py-2"
>
<div
v-for="(node, i) in uniqueNodes"
:key="i"
class="flex min-h-8 items-center justify-between px-4 py-2 bg-secondary-background text-muted-foreground"
class="flex min-h-8 items-center justify-between bg-secondary-background px-4 py-2 text-muted-foreground"
>
<span class="text-xs">
{{ node.label }}
</span>
<span v-if="node.hint" class="text-xs">{{ node.hint }}</span>
<span
v-if="node.hint"
class="text-xs"
>{{ node.hint }}</span>
</div>
</div>

View File

@@ -2,7 +2,7 @@
<!-- Cloud mode: Learn More + Got It buttons -->
<div
v-if="isCloud"
class="flex w-full items-center justify-between gap-2 py-2 px-4"
class="flex w-full items-center justify-between gap-2 px-4 py-2"
>
<Button
variant="textonly"
@@ -12,19 +12,33 @@
target="_blank"
rel="noopener noreferrer"
>
<i class="icon-[lucide--info]"></i>
<i class="icon-[lucide--info]" />
<span>{{ $t('missingNodes.cloud.learnMore') }}</span>
</Button>
<Button variant="secondary" size="md" @click="handleGotItClick">{{
<Button
variant="secondary"
size="md"
@click="handleGotItClick"
>
{{
$t('missingNodes.cloud.gotIt')
}}</Button>
}}
</Button>
</div>
<!-- OSS mode: Open Manager + Install All buttons -->
<div v-else-if="showManagerButtons" class="flex justify-end gap-1 py-2 px-4">
<Button variant="textonly" @click="openManager">{{
<div
v-else-if="showManagerButtons"
class="flex justify-end gap-1 px-4 py-2"
>
<Button
variant="textonly"
@click="openManager"
>
{{
$t('g.openManager')
}}</Button>
}}
</Button>
<PackInstallButton
v-if="showInstallAllButton"
type="secondary"

View File

@@ -3,8 +3,8 @@
class="flex min-w-[460px] flex-col rounded-2xl border border-border-default bg-base-background shadow-[1px_1px_8px_0_rgba(0,0,0,0.4)]"
>
<!-- Header -->
<div class="flex py-8 items-center justify-between px-8">
<h2 class="text-lg font-bold text-base-foreground m-0">
<div class="flex items-center justify-between px-8 py-8">
<h2 class="m-0 text-lg font-bold text-base-foreground">
{{
isInsufficientCredits
? $t('credits.topUp.addMoreCreditsToRun')
@@ -12,7 +12,7 @@
}}
</h2>
<button
class="cursor-pointer rounded border-none bg-transparent p-0 text-muted-foreground transition-colors hover:text-base-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-secondary-foreground"
class="focus-visible:ring-secondary-foreground cursor-pointer rounded border-none bg-transparent p-0 text-muted-foreground transition-colors hover:text-base-foreground focus-visible:ring-1 focus-visible:outline-none"
@click="() => handleClose()"
>
<i class="icon-[lucide--x] size-6" />
@@ -20,7 +20,7 @@
</div>
<p
v-if="isInsufficientCredits"
class="text-sm text-muted-foreground m-0 px-8"
class="m-0 px-8 text-sm text-muted-foreground"
>
{{ $t('credits.topUp.insufficientWorkflowMessage') }}
</p>
@@ -39,7 +39,7 @@
size="lg"
:class="
cn(
'h-10 text-base font-medium w-full focus-visible:ring-secondary-foreground',
'focus-visible:ring-secondary-foreground h-10 w-full text-base font-medium',
selectedPreset === amount && 'bg-secondary-background-selected'
)
"
@@ -65,9 +65,7 @@
@max-reached="showCeilingWarning = true"
>
<template #prefix>
<span class="shrink-0 text-base font-semibold text-base-foreground"
>$</span
>
<span class="shrink-0 text-base font-semibold text-base-foreground">$</span>
</template>
</FormattedNumberStepper>
</div>
@@ -95,7 +93,7 @@
<p
v-if="isBelowMin"
class="text-sm text-red-500 m-0 px-8 pt-4 text-center flex items-center justify-center gap-1"
class="m-0 flex items-center justify-center gap-1 px-8 pt-4 text-center text-sm text-red-500"
>
<i class="icon-[lucide--component] size-4" />
{{
@@ -106,7 +104,7 @@
</p>
<p
v-if="showCeilingWarning"
class="text-sm text-gold-500 m-0 px-8 pt-4 text-center flex items-center justify-center gap-1"
class="m-0 flex items-center justify-center gap-1 px-8 pt-4 text-center text-sm text-gold-500"
>
<i class="icon-[lucide--component] size-4" />
{{
@@ -119,11 +117,10 @@
href="https://www.comfy.org/cloud/enterprise"
target="_blank"
class="ml-1 text-inherit"
>{{ $t('credits.topUp.contactUs') }}</a
>
>{{ $t('credits.topUp.contactUs') }}</a>
</p>
<div class="pt-8 pb-8 flex flex-col gap-8 px-8">
<div class="flex flex-col gap-8 px-8 pt-8 pb-8">
<Button
:disabled="!isValidAmount || loading"
:loading="loading"

View File

@@ -1,10 +1,10 @@
<template>
<div
class="flex items-center justify-between p-2 rounded-lg cursor-pointer transition-all duration-200"
class="flex cursor-pointer items-center justify-between rounded-lg p-2 transition-all duration-200"
:class="[
selected
? 'bg-secondary-background border-2 border-border-default'
: 'bg-component-node-disabled hover:bg-secondary-background border-2 border-transparent'
? 'border-2 border-border-default bg-secondary-background'
: 'bg-component-node-disabled border-2 border-transparent hover:bg-secondary-background'
]"
@click="$emit('select')"
>

View File

@@ -7,7 +7,10 @@
>
<!-- Email Field -->
<div class="flex flex-col gap-2">
<label class="mb-2 text-base font-medium opacity-80" :for="emailInputId">
<label
class="mb-2 text-base font-medium opacity-80"
:for="emailInputId"
>
{{ t('auth.login.emailLabel') }}
</label>
<InputText
@@ -19,7 +22,10 @@
:placeholder="t('auth.login.emailPlaceholder')"
:invalid="$form.email?.invalid"
/>
<small v-if="$form.email?.invalid" class="text-red-500">{{
<small
v-if="$form.email?.invalid"
class="text-red-500"
>{{
$form.email.error.message
}}</small>
</div>
@@ -54,13 +60,19 @@
fluid
class="h-10"
/>
<small v-if="$form.password?.invalid" class="text-red-500">{{
<small
v-if="$form.password?.invalid"
class="text-red-500"
>{{
$form.password.error.message
}}</small>
</div>
<!-- Submit Button -->
<ProgressSpinner v-if="loading" class="mx-auto h-8 w-8" />
<ProgressSpinner
v-if="loading"
class="mx-auto h-8 w-8"
/>
<Button
v-else
type="submit"
@@ -131,6 +143,6 @@ const handleForgotPassword = async (
@reference '../../../../assets/css/style.css';
.text-link-disabled {
@apply opacity-50 cursor-not-allowed;
@apply cursor-not-allowed opacity-50;
}
</style>

View File

@@ -2,7 +2,7 @@
<ContextMenu
ref="contextMenu"
:model="menuItems"
class="max-h-[80vh] md:max-h-none overflow-y-auto md:overflow-y-visible"
class="max-h-[80vh] overflow-y-auto md:max-h-none md:overflow-y-visible"
@show="onMenuShow"
@hide="onMenuHide"
>
@@ -12,7 +12,10 @@
class="flex items-center gap-2 px-3 py-1.5"
@click="item.isColorSubmenu ? showColorPopover($event) : undefined"
>
<i v-if="item.icon" :class="[item.icon, 'size-4']" />
<i
v-if="item.icon"
:class="[item.icon, 'size-4']"
/>
<span class="flex-1">{{ item.label }}</span>
<span
v-if="item.shortcut"

View File

@@ -11,7 +11,10 @@
@click="() => (showColorPicker = !showColorPicker)"
>
<div class="flex items-center gap-1 px-0">
<i class="pi pi-circle-fill" :style="{ color: currentColor ?? '' }" />
<i
class="pi pi-circle-fill"
:style="{ color: currentColor ?? '' }"
/>
<i class="icon-[lucide--chevron-down]" />
</div>
</Button>
@@ -166,6 +169,6 @@ watch(
}
:deep(.p-togglebutton) {
@apply py-2 px-1;
@apply px-1 py-2;
}
</style>

View File

@@ -23,7 +23,7 @@
:class="
isColorSubmenu
? 'flex flex-col gap-1 p-2'
: 'flex flex-col p-2 min-w-40'
: 'flex min-w-40 flex-col p-2'
"
>
<div
@@ -31,12 +31,12 @@
:key="subOption.label"
:class="
cn(
'hover:bg-secondary-background-hover rounded cursor-pointer',
'cursor-pointer rounded hover:bg-secondary-background-hover',
isColorSubmenu
? 'w-7 h-7 flex items-center justify-center'
? 'flex h-7 w-7 items-center justify-center'
: 'flex items-center gap-2 px-3 py-1.5 text-sm',
subOption.disabled
? 'cursor-not-allowed pointer-events-none text-node-icon-disabled'
? 'pointer-events-none cursor-not-allowed text-node-icon-disabled'
: 'hover:bg-secondary-background-hover'
)
"
@@ -53,7 +53,10 @@
v-if="isShapeSelected(subOption)"
class="icon-[lucide--check] size-4 flex-shrink-0"
/>
<div v-else class="w-4 flex-shrink-0" />
<div
v-else
class="w-4 flex-shrink-0"
/>
<span>{{ subOption.label }}</span>
</template>
</div>

View File

@@ -6,7 +6,10 @@
>
<!-- Main Menu Items -->
<div class="w-full">
<nav class="flex w-full flex-col gap-2" role="menubar">
<nav
class="flex w-full flex-col gap-2"
role="menubar"
>
<button
v-for="menuItem in menuItems"
v-show="menuItem.visible !== false"
@@ -26,14 +29,20 @@
v-if="typeof menuItem.icon === 'object'"
:size="16"
/>
<i v-else :class="menuItem.icon" />
<i
v-else
:class="menuItem.icon"
/>
</div>
<div v-if="menuItem.showRedDot" class="menu-red-dot" />
<div
v-if="menuItem.showRedDot"
class="menu-red-dot"
/>
</div>
<span class="menu-label">{{ menuItem.label }}</span>
<i
v-if="menuItem.showExternalIcon"
class="icon-[lucide--external-link] text-primary w-4 h-4 ml-auto"
class="ml-auto icon-[lucide--external-link] h-4 w-4 text-primary"
/>
<i
v-if="menuItem.key === 'more'"
@@ -109,7 +118,10 @@
@keydown.enter="onReleaseClick(release)"
@keydown.space.prevent="onReleaseClick(release)"
>
<i class="help-menu-icon icon-[lucide--package]" aria-hidden="true" />
<i
class="help-menu-icon icon-[lucide--package]"
aria-hidden="true"
/>
<div class="release-content">
<span class="release-title">
{{
@@ -119,7 +131,10 @@
})
}}
</span>
<time class="release-date" :datetime="release.published_at">
<time
class="release-date"
:datetime="release.published_at"
>
<span class="normal-state">
{{ formatReleaseDate(release.published_at) }}
</span>
@@ -138,13 +153,23 @@
role="status"
aria-live="polite"
>
<i class="pi pi-spin pi-spinner help-menu-icon" aria-hidden="true" />
<i
class="pi pi-spin pi-spinner help-menu-icon"
aria-hidden="true"
/>
<span>{{ $t('helpCenter.loadingReleases') }}</span>
</div>
<!-- No Releases State -->
<div v-else class="help-menu-item" role="status">
<i class="pi pi-info-circle help-menu-icon" aria-hidden="true" />
<div
v-else
class="help-menu-item"
role="status"
>
<i
class="pi pi-info-circle help-menu-icon"
aria-hidden="true"
/>
<span>{{ $t('helpCenter.noRecentReleases') }}</span>
</div>
</section>

View File

@@ -10,7 +10,10 @@
ref="containerEl"
class="relative min-h-0 flex-1 overflow-hidden rounded-[5px] bg-node-component-surface"
>
<div v-if="isLoading" class="flex size-full items-center justify-center">
<div
v-if="isLoading"
class="flex size-full items-center justify-center"
>
<span class="text-sm">{{ $t('imageCrop.loading') }}</span>
</div>
@@ -19,7 +22,9 @@
class="flex size-full flex-col items-center justify-center text-center"
>
<i class="mb-2 icon-[lucide--image] h-12 w-12" />
<p class="text-sm">{{ $t('imageCrop.noInputImage') }}</p>
<p class="text-sm">
{{ $t('imageCrop.noInputImage') }}
</p>
</div>
<img
@@ -28,11 +33,11 @@
:src="imageUrl"
:alt="$t('imageCrop.cropPreviewAlt')"
draggable="false"
class="block size-full object-contain select-none brightness-50"
class="block size-full object-contain brightness-50 select-none"
@load="handleImageLoad"
@error="handleImageError"
@dragstart.prevent
/>
>
<div
v-if="imageUrl && !isLoading"
@@ -42,7 +47,10 @@
@pointermove="handleDragMove"
@pointerup="handleDragEnd"
>
<div class="pointer-events-none size-full" :style="cropImageStyle" />
<div
class="pointer-events-none size-full"
:style="cropImageStyle"
/>
</div>
<div
@@ -57,7 +65,10 @@
/>
</div>
<WidgetBoundingBox v-model="modelValue" class="shrink-0" />
<WidgetBoundingBox
v-model="modelValue"
class="shrink-0"
/>
</div>
</template>

View File

@@ -121,7 +121,7 @@
{{ $t('g.clearAll') }}
</Button>
</div>
<div class="my-4 h-px bg-border-default"></div>
<div class="my-4 h-px bg-border-default" />
</div>
</template>
@@ -147,7 +147,7 @@
<template #option="slotProps">
<div
role="button"
class="flex items-center gap-2 cursor-pointer"
class="flex cursor-pointer items-center gap-2"
:style="popoverStyle"
>
<div

View File

@@ -1,7 +1,7 @@
<template>
<div
ref="container"
class="relative h-full w-full min-h-[200px]"
class="relative h-full min-h-[200px] w-full"
data-capture-wheel="true"
@pointerdown.stop
@pointermove.stop
@@ -14,7 +14,10 @@
@dragleave.stop="handleDragLeave"
@drop.prevent.stop="handleDrop"
>
<LoadingOverlay :loading="loading" :loading-message="loadingMessage" />
<LoadingOverlay
:loading="loading"
:loading-message="loadingMessage"
/>
<div
v-if="!isPreview && isDragging"
class="pointer-events-none absolute inset-0 z-50 flex items-center justify-center bg-black/60 backdrop-blur-sm"

View File

@@ -1,5 +1,5 @@
<template>
<div class="relative show-slider">
<div class="show-slider relative">
<Button
v-tooltip.right="{ value: tooltipText, showDelay: 300 }"
size="icon"
@@ -12,7 +12,7 @@
</Button>
<div
v-show="showSlider"
class="absolute top-0 left-12 rounded-lg bg-interface-menu-surface p-4 shadow-lg w-[150px]"
class="absolute top-0 left-12 w-[150px] rounded-lg bg-interface-menu-surface p-4 shadow-lg"
>
<Slider
v-model="value"

View File

@@ -13,7 +13,7 @@
:class="
cn(
'rounded-full',
isRecording && 'text-red-500 recording-button-blink'
isRecording && 'recording-button-blink text-red-500'
)
"
:aria-label="

View File

@@ -1,75 +1,78 @@
<template>
<div class="flex flex-col gap-3 pb-3">
<h3 class="text-center text-[15px] font-sans text-descrip-text mt-2.5">
<h3 class="text-descrip-text mt-2.5 text-center font-sans text-[15px]">
{{ t('maskEditor.brushSettings') }}
</h3>
<button :class="textButtonClass" @click="resetToDefault">
<button
:class="textButtonClass"
@click="resetToDefault"
>
{{ t('maskEditor.resetToDefault') }}
</button>
<!-- Brush Shape -->
<div class="flex flex-col gap-3 pb-3">
<span class="text-left text-xs font-sans text-descrip-text">
<span class="text-descrip-text text-left font-sans text-xs">
{{ t('maskEditor.brushShape') }}
</span>
<div
class="flex flex-row gap-2.5 items-center h-[50px] w-full rounded-[10px] bg-secondary-background-hover"
class="flex h-[50px] w-full flex-row items-center gap-2.5 rounded-[10px] bg-secondary-background-hover"
>
<div
class="maskEditor_sidePanelBrushShapeCircle hover:bg-comfy-menu-bg"
:class="
cn(
store.brushSettings.type === BrushShape.Arc
? 'bg-[var(--p-button-text-primary-color)] active'
? 'active bg-[var(--p-button-text-primary-color)]'
: 'bg-transparent'
)
"
@click="setBrushShape(BrushShape.Arc)"
></div>
/>
<div
class="maskEditor_sidePanelBrushShapeSquare hover:bg-comfy-menu-bg"
:class="
cn(
store.brushSettings.type === BrushShape.Rect
? 'bg-[var(--p-button-text-primary-color)] active'
? 'active bg-[var(--p-button-text-primary-color)]'
: 'bg-transparent'
)
"
@click="setBrushShape(BrushShape.Rect)"
></div>
/>
</div>
</div>
<!-- Color -->
<div class="flex flex-col gap-3 pb-3">
<span class="text-left text-xs font-sans text-descrip-text">
<span class="text-descrip-text text-left font-sans text-xs">
{{ t('maskEditor.colorSelector') }}
</span>
<input
ref="colorInputRef"
v-model="store.rgbColor"
type="color"
class="h-10 rounded-md cursor-pointer"
/>
class="h-10 cursor-pointer rounded-md"
>
</div>
<!-- Thickness -->
<div class="flex flex-col gap-2">
<div class="flex items-center justify-between">
<span class="text-left text-xs font-sans text-descrip-text">
<span class="text-descrip-text text-left font-sans text-xs">
{{ t('maskEditor.thickness') }}
</span>
<input
v-model.number="brushSize"
type="number"
class="w-16 px-2 py-1 text-sm text-center border rounded-md bg-comfy-menu-bg border-p-form-field-border-color text-input-text"
class="border-p-form-field-border-color text-input-text w-16 rounded-md border bg-comfy-menu-bg px-2 py-1 text-center text-sm"
:min="1"
:max="250"
:step="1"
/>
>
</div>
<SliderControl
v-model="brushSize"
@@ -84,17 +87,17 @@
<!-- Opacity -->
<div class="flex flex-col gap-2">
<div class="flex items-center justify-between">
<span class="text-left text-xs font-sans text-descrip-text">
<span class="text-descrip-text text-left font-sans text-xs">
{{ t('maskEditor.opacity') }}
</span>
<input
v-model.number="brushOpacity"
type="number"
class="w-16 px-2 py-1 text-sm text-center border rounded-md bg-comfy-menu-bg border-p-form-field-border-color text-input-text"
class="border-p-form-field-border-color text-input-text w-16 rounded-md border bg-comfy-menu-bg px-2 py-1 text-center text-sm"
:min="0"
:max="1"
:step="0.01"
/>
>
</div>
<SliderControl
v-model="brushOpacity"
@@ -109,17 +112,17 @@
<!-- Hardness -->
<div class="flex flex-col gap-2">
<div class="flex items-center justify-between">
<span class="text-left text-xs font-sans text-descrip-text">
<span class="text-descrip-text text-left font-sans text-xs">
{{ t('maskEditor.hardness') }}
</span>
<input
v-model.number="brushHardness"
type="number"
class="w-16 px-2 py-1 text-sm text-center border rounded-md bg-comfy-menu-bg border-p-form-field-border-color text-input-text"
class="border-p-form-field-border-color text-input-text w-16 rounded-md border bg-comfy-menu-bg px-2 py-1 text-center text-sm"
:min="0"
:max="1"
:step="0.01"
/>
>
</div>
<SliderControl
v-model="brushHardness"
@@ -134,17 +137,17 @@
<!-- Step Size -->
<div class="flex flex-col gap-2">
<div class="flex items-center justify-between">
<span class="text-left text-xs font-sans text-descrip-text">
<span class="text-descrip-text text-left font-sans text-xs">
{{ t('maskEditor.stepSize') }}
</span>
<input
v-model.number="brushStepSize"
type="number"
class="w-16 px-2 py-1 text-sm text-center border rounded-md bg-comfy-menu-bg border-p-form-field-border-color text-input-text"
class="border-p-form-field-border-color text-input-text w-16 rounded-md border bg-comfy-menu-bg px-2 py-1 text-center text-sm"
:min="1"
:max="100"
:step="1"
/>
>
</div>
<SliderControl
v-model="brushStepSize"

View File

@@ -1,7 +1,7 @@
<template>
<div class="flex flex-col gap-3 pb-3">
<h3
class="text-center text-[15px] font-sans text-[var(--descrip-text)] mt-2.5"
class="mt-2.5 text-center font-sans text-[15px] text-[var(--descrip-text)]"
>
{{ t('maskEditor.colorSelectSettings') }}
</h3>

View File

@@ -1,7 +1,7 @@
<template>
<div class="flex flex-col gap-3 pb-3">
<h3
class="text-center text-[15px] font-sans text-[var(--descrip-text)] mt-2.5"
class="mt-2.5 text-center font-sans text-[15px] text-[var(--descrip-text)]"
>
{{ t('maskEditor.layers') }}
</h3>
@@ -15,29 +15,35 @@
@update:model-value="onMaskOpacityChange"
/>
<span class="text-left text-xs font-sans text-[var(--descrip-text)]">{{
<span class="text-left font-sans text-xs text-[var(--descrip-text)]">{{
t('maskEditor.maskBlendingOptions')
}}</span>
<div
class="flex flex-row gap-2.5 items-center min-h-6 relative h-[50px] w-full rounded-[10px] -mt-2 -mb-1.5"
class="relative -mt-2 -mb-1.5 flex h-[50px] min-h-6 w-full flex-row items-center gap-2.5 rounded-[10px]"
>
<select
class="maskEditor_sidePanelDropdown"
:value="store.maskBlendMode"
@change="onBlendModeChange"
>
<option value="black">{{ t('maskEditor.black') }}</option>
<option value="white">{{ t('maskEditor.white') }}</option>
<option value="negative">{{ t('maskEditor.negative') }}</option>
<option value="black">
{{ t('maskEditor.black') }}
</option>
<option value="white">
{{ t('maskEditor.white') }}
</option>
<option value="negative">
{{ t('maskEditor.negative') }}
</option>
</select>
</div>
<span class="text-left text-xs font-sans text-[var(--descrip-text)]">{{
<span class="text-left font-sans text-xs text-[var(--descrip-text)]">{{
t('maskEditor.maskLayer')
}}</span>
<div
class="flex flex-row gap-2.5 items-center min-h-6 relative h-[50px] w-full rounded-[10px] bg-secondary-background-hover"
class="relative flex h-[50px] min-h-6 w-full flex-row items-center gap-2.5 rounded-[10px] bg-secondary-background-hover"
:style="{
border: store.activeLayer === 'mask' ? '2px solid #007acc' : 'none'
}"
@@ -47,9 +53,12 @@
class="maskEditor_sidePanelLayerCheckbox"
:checked="maskLayerVisible"
@change="onMaskLayerVisibilityChange"
/>
>
<div class="maskEditor_sidePanelLayerPreviewContainer">
<svg viewBox="0 0 20 20" style="">
<svg
viewBox="0 0 20 20"
style=""
>
<path
class="cls-1"
d="M1.31,5.32v9.36c0,.55.45,1,1,1h15.38c.55,0,1-.45,1-1V5.32c0-.55-.45-1-1-1H2.31c-.55,0-1,.45-1,1ZM11.19,13.44c-2.91.94-5.57-1.72-4.63-4.63.34-1.05,1.19-1.9,2.24-2.24,2.91-.94,5.57,1.72,4.63,4.63-.34,1.05-1.19-1.9-2.24,2.24Z"
@@ -66,11 +75,11 @@
</button>
</div>
<span class="text-left text-xs font-sans text-[var(--descrip-text)]">{{
<span class="text-left font-sans text-xs text-[var(--descrip-text)]">{{
t('maskEditor.paintLayer')
}}</span>
<div
class="flex flex-row gap-2.5 items-center min-h-6 relative h-[50px] w-full rounded-[10px] bg-secondary-background-hover"
class="relative flex h-[50px] min-h-6 w-full flex-row items-center gap-2.5 rounded-[10px] bg-secondary-background-hover"
:style="{
border: store.activeLayer === 'rgb' ? '2px solid #007acc' : 'none'
}"
@@ -80,7 +89,7 @@
class="maskEditor_sidePanelLayerCheckbox"
:checked="paintLayerVisible"
@change="onPaintLayerVisibilityChange"
/>
>
<div class="maskEditor_sidePanelLayerPreviewContainer">
<svg viewBox="0 0 20 20">
<path
@@ -106,24 +115,24 @@
</button>
</div>
<span class="text-left text-xs font-sans text-[var(--descrip-text)]">{{
<span class="text-left font-sans text-xs text-[var(--descrip-text)]">{{
t('maskEditor.baseImageLayer')
}}</span>
<div
class="flex flex-row gap-2.5 items-center min-h-6 relative h-[50px] w-full rounded-[10px] bg-secondary-background-hover"
class="relative flex h-[50px] min-h-6 w-full flex-row items-center gap-2.5 rounded-[10px] bg-secondary-background-hover"
>
<input
type="checkbox"
class="maskEditor_sidePanelLayerCheckbox"
:checked="baseImageLayerVisible"
@change="onBaseImageLayerVisibilityChange"
/>
>
<div class="maskEditor_sidePanelLayerPreviewContainer">
<img
class="maskEditor_sidePanelImageLayerImage"
:src="baseImageSrc"
:alt="t('maskEditor.baseLayerPreview')"
/>
>
</div>
</div>
</div>

View File

@@ -13,29 +13,32 @@
>
<canvas
ref="imgCanvasRef"
class="absolute top-0 left-0 w-full h-full z-0"
class="absolute top-0 left-0 z-0 h-full w-full"
@contextmenu.prevent
/>
<canvas
ref="rgbCanvasRef"
class="absolute top-0 left-0 w-full h-full z-10"
class="absolute top-0 left-0 z-10 h-full w-full"
@contextmenu.prevent
/>
<canvas
ref="maskCanvasRef"
class="absolute top-0 left-0 w-full h-full z-30"
class="absolute top-0 left-0 z-30 h-full w-full"
@contextmenu.prevent
/>
<!-- GPU Preview Canvas -->
<canvas
ref="gpuCanvasRef"
class="absolute top-0 left-0 w-full h-full pointer-events-none"
class="pointer-events-none absolute top-0 left-0 h-full w-full"
:class="{
'z-20': store.activeLayer === 'rgb',
'z-40': store.activeLayer === 'mask'
}"
/>
<div ref="canvasBackgroundRef" class="bg-white w-full h-full" />
<div
ref="canvasBackgroundRef"
class="h-full w-full bg-white"
/>
</div>
<div class="maskEditor-ui-container flex min-h-0 flex-1 flex-col">
@@ -60,7 +63,10 @@
</div>
</div>
<BrushCursor v-if="initialized" :container-ref="containerRef" />
<BrushCursor
v-if="initialized"
:container-ref="containerRef"
/>
</div>
</template>

View File

@@ -1,7 +1,7 @@
<template>
<div class="flex flex-col gap-3 pb-3">
<h3
class="text-center text-[15px] font-sans text-[var(--descrip-text)] mt-2.5"
class="mt-2.5 text-center font-sans text-[15px] text-[var(--descrip-text)]"
>
{{ t('maskEditor.paintBucketSettings') }}
</h3>

View File

@@ -1,7 +1,7 @@
<template>
<div
ref="pointerZoneRef"
class="w-[calc(100%-4rem-220px)] h-full"
class="h-full w-[calc(100%-4rem-220px)]"
@pointerdown="handlePointerDown"
@pointermove="handlePointerMove"
@pointerup="handlePointerUp"

View File

@@ -1,11 +1,11 @@
<template>
<div
class="flex flex-col gap-3 pb-3 h-full !items-stretch bg-[var(--comfy-menu-bg)] overflow-y-auto w-55 px-2.5"
class="flex h-full w-55 flex-col !items-stretch gap-3 overflow-y-auto bg-[var(--comfy-menu-bg)] px-2.5 pb-3"
>
<div class="w-full min-h-full">
<div class="min-h-full w-full">
<SettingsPanelContainer />
<div class="w-full h-0.5 bg-[var(--border-color)] mt-6 mb-1.5" />
<div class="mt-6 mb-1.5 h-0.5 w-full bg-[var(--border-color)]" />
<ImageLayerSettingsPanel :tool-manager="toolManager" />
</div>

View File

@@ -1,5 +1,5 @@
<template>
<div class="h-full z-8888 flex flex-col justify-between bg-comfy-menu-bg">
<div class="z-8888 flex h-full flex-col justify-between bg-comfy-menu-bg">
<div class="flex flex-col">
<div
v-for="tool in allTools"
@@ -13,13 +13,13 @@
<div
class="flex items-center justify-center"
v-html="iconsHtml[tool]"
></div>
<div class="maskEditor_toolPanelIndicator"></div>
/>
<div class="maskEditor_toolPanelIndicator" />
</div>
</div>
<div
class="flex flex-col items-center cursor-pointer rounded-md mb-2 transition-colors duration-200 hover:bg-secondary-background-hover"
class="mb-2 flex cursor-pointer flex-col items-center rounded-md transition-colors duration-200 hover:bg-secondary-background-hover"
:title="t('maskEditor.clickToResetZoom')"
@click="onResetZoom"
>

View File

@@ -1,10 +1,10 @@
<template>
<div class="flex flex-row gap-2.5 items-center min-h-6 relative">
<span class="text-left text-xs font-sans text-[var(--descrip-text)]">{{
<div class="relative flex min-h-6 flex-row items-center gap-2.5">
<span class="text-left font-sans text-xs text-[var(--descrip-text)]">{{
label
}}</span>
<select
class="absolute right-0 h-6 px-1.5 rounded-md border border-border-default transition-colors duration-100 bg-secondary-background focus:outline focus:outline-node-component-border"
class="absolute right-0 h-6 rounded-md border border-border-default bg-secondary-background px-1.5 transition-colors duration-100 focus:outline focus:outline-node-component-border"
:value="modelValue"
@change="onChange"
>

View File

@@ -1,6 +1,6 @@
<template>
<div class="flex flex-col gap-3 pb-3">
<span class="text-left text-xs font-sans text-[var(--descrip-text)]">{{
<span class="text-left font-sans text-xs text-[var(--descrip-text)]">{{
label
}}</span>
<input
@@ -11,7 +11,7 @@
:step="step"
:value="modelValue"
@input="onInput"
/>
>
</div>
</template>

View File

@@ -1,6 +1,6 @@
<template>
<div class="flex flex-row gap-2.5 items-center min-h-6 relative">
<span class="text-left text-xs font-sans text-[var(--descrip-text)]">{{
<div class="relative flex min-h-6 flex-row items-center gap-2.5">
<span class="text-left font-sans text-xs text-[var(--descrip-text)]">{{
label
}}</span>
<label class="maskEditor_sidePanelToggleContainer">
@@ -9,8 +9,8 @@
class="maskEditor_sidePanelToggleCheckbox"
:checked="modelValue"
@change="onChange"
/>
<div class="maskEditor_sidePanelToggleSwitch"></div>
>
<div class="maskEditor_sidePanelToggleSwitch" />
</label>
</div>
</template>

View File

@@ -1,7 +1,9 @@
<template>
<div class="flex w-full items-center justify-between gap-3">
<div class="flex items-center gap-3">
<h3 class="m-0 text-lg font-semibold">{{ t('maskEditor.title') }}</h3>
<h3 class="m-0 text-lg font-semibold">
{{ t('maskEditor.title') }}
</h3>
<div class="flex items-center gap-4">
<button
@@ -11,7 +13,7 @@
>
<svg
viewBox="0 0 15 15"
class="h-6.25 w-6.25 pointer-events-none fill-current"
class="pointer-events-none h-6.25 w-6.25 fill-current"
>
<path
d="M8.77,12.18c-.25,0-.46-.2-.46-.46s.2-.46.46-.46c1.47,0,2.67-1.2,2.67-2.67,0-1.57-1.34-2.67-3.26-2.67h-3.98l1.43,1.43c.18.18.18.47,0,.64-.18.18-.47.18-.64,0l-2.21-2.21c-.18-.18-.18-.47,0-.64l2.21-2.21c.18-.18.47-.18.64,0,.18.18.18.47,0,.64l-1.43,1.43h3.98c2.45,0,4.17,1.47,4.17,3.58,0,1.97-1.61,3.58-3.58,3.58Z"
@@ -26,7 +28,7 @@
>
<svg
viewBox="0 0 15 15"
class="h-6.25 w-6.25 pointer-events-none fill-[var(--input-text)]"
class="pointer-events-none h-6.25 w-6.25 fill-[var(--input-text)]"
>
<path
class="cls-1"
@@ -35,7 +37,7 @@
</svg>
</button>
<div class="h-5 border-l border-border" />
<div class="border-border h-5 border-l" />
<button
:class="iconButtonClass"
@@ -44,7 +46,7 @@
>
<svg
viewBox="-6 -7 15 15"
class="h-6.25 w-6.25 pointer-events-none fill-[var(--input-text)]"
class="pointer-events-none h-6.25 w-6.25 fill-[var(--input-text)]"
>
<path
d="m2.25-2.625c.3452 0 .625.2798.625.625v5c0 .3452-.2798.625-.625.625h-5c-.3452 0-.625-.2798-.625-.625v-5c0-.3452.2798-.625.625-.625h5zm1.25.625v5c0 .6904-.5596 1.25-1.25 1.25h-5c-.6904 0-1.25-.5596-1.25-1.25v-5c0-.6904.5596-1.25 1.25-1.25h5c.6904 0 1.25.5596 1.25 1.25zm-.1673-2.3757-.4419.4419-1.5246-1.5246 1.5416-1.5417.442.4419-.7871.7872h.9373c1.3807 0 2.5 1.1193 2.5 2.5h-.625c0-1.0355-.8395-1.875-1.875-1.875h-.9375l.7702.7702z"
@@ -59,7 +61,7 @@
>
<svg
viewBox="-9 -7 15 15"
class="h-6.25 w-6.25 pointer-events-none fill-[var(--input-text)]"
class="pointer-events-none h-6.25 w-6.25 fill-[var(--input-text)]"
>
<g transform="scale(-1, 1)">
<path
@@ -76,7 +78,7 @@
>
<svg
viewBox="0 0 15 15"
class="h-6.25 w-6.25 pointer-events-none fill-[var(--input-text)]"
class="pointer-events-none h-6.25 w-6.25 fill-[var(--input-text)]"
>
<path
d="M7.5,1.5c-.28,0-.5.22-.5.5v11c0,.28.22.5.5.5s.5-.22.5-.5v-11c0-.28-.22-.5-.5-.5Z"
@@ -92,7 +94,7 @@
>
<svg
viewBox="0 0 15 15"
class="h-6.25 w-6.25 pointer-events-none fill-[var(--input-text)]"
class="pointer-events-none h-6.25 w-6.25 fill-[var(--input-text)]"
>
<path
d="M2,7.5c0-.28.22-.5.5-.5h11c.28,0,.5.22.5.5s-.22.5-.5.5h-11c-.28,0-.5-.22-.5-.5Z"
@@ -103,22 +105,35 @@
<div class="h-5 w-px bg-[var(--p-form-field-border-color)]" />
<button :class="textButtonClass" @click="onInvert">
<button
:class="textButtonClass"
@click="onInvert"
>
{{ t('maskEditor.invert') }}
</button>
<button :class="textButtonClass" @click="onClear">
<button
:class="textButtonClass"
@click="onClear"
>
{{ t('maskEditor.clear') }}
</button>
</div>
</div>
<div class="flex gap-3">
<Button variant="primary" :disabled="!saveEnabled" @click="handleSave">
<Button
variant="primary"
:disabled="!saveEnabled"
@click="handleSave"
>
<i class="pi pi-check" />
{{ saveButtonText }}
</Button>
<Button variant="secondary" @click="handleCancel">
<Button
variant="secondary"
@click="handleCancel"
>
<i class="pi pi-times" />
{{ t('g.cancel') }}
</Button>

View File

@@ -12,7 +12,10 @@
v-html="renderedHelpHtml"
/>
<!-- Fallback: markdown not found or fetch error -->
<div v-else class="fallback-content space-y-6 text-sm">
<div
v-else
class="fallback-content space-y-6 text-sm"
>
<p v-if="node.description">
<strong>{{ $t('g.description') }}:</strong> {{ node.description }}
</p>
@@ -31,7 +34,10 @@
</tr>
</thead>
<tbody>
<tr v-for="input in inputList" :key="input.name">
<tr
v-for="input in inputList"
:key="input.name"
>
<td>
<code>{{ input.name }}</code>
</td>
@@ -55,7 +61,10 @@
</tr>
</thead>
<tbody>
<tr v-for="output in outputList" :key="output.name">
<tr
v-for="output in outputList"
:key="output.name"
>
<td>
<code>{{ output.name }}</code>
</td>
@@ -103,27 +112,27 @@ const outputList = computed(() =>
@reference './../../assets/css/style.css';
.node-help-content :deep(:is(img, video)) {
@apply max-w-full h-auto block mb-4;
@apply mb-4 block h-auto max-w-full;
}
.markdown-content,
.fallback-content {
@apply text-sm overflow-visible;
@apply overflow-visible text-sm;
}
.markdown-content :deep(h1),
.fallback-content h1 {
@apply text-[22px] font-bold mt-8 mb-4 first:mt-0;
@apply mt-8 mb-4 text-[22px] font-bold first:mt-0;
}
.markdown-content :deep(h2),
.fallback-content h2 {
@apply text-[18px] font-bold mt-8 mb-4 first:mt-0;
@apply mt-8 mb-4 text-[18px] font-bold first:mt-0;
}
.markdown-content :deep(h3),
.fallback-content h3 {
@apply text-[16px] font-bold mt-8 mb-4 first:mt-0;
@apply mt-8 mb-4 text-[16px] font-bold first:mt-0;
}
.markdown-content :deep(h4),
@@ -155,7 +164,7 @@ const outputList = computed(() =>
.markdown-content :deep(ol),
.fallback-content ul,
.fallback-content ol {
@apply pl-8 my-2;
@apply my-2 pl-8;
}
.markdown-content :deep(ul ul),
@@ -166,7 +175,7 @@ const outputList = computed(() =>
.fallback-content ol ol,
.fallback-content ul ol,
.fallback-content ol ul {
@apply pl-6 my-2;
@apply my-2 pl-6;
}
.markdown-content :deep(li),
@@ -215,7 +224,7 @@ const outputList = computed(() =>
.markdown-content :deep(pre),
.fallback-content pre {
@apply rounded p-4 my-4 overflow-x-auto;
@apply my-4 overflow-x-auto rounded p-4;
background-color: var(--code-block-bg-color);
code {

View File

@@ -9,7 +9,7 @@
<div class="flex items-center justify-between px-3">
<Button
class="grow gap-1 justify-center"
class="grow justify-center gap-1"
variant="secondary"
size="sm"
@click="$emit('showAssets')"
@@ -51,7 +51,7 @@
@update:selected-sort-mode="$emit('update:selectedSortMode', $event)"
/>
<div class="flex-1 min-h-0 overflow-y-auto">
<div class="min-h-0 flex-1 overflow-y-auto">
<JobGroupsList
:displayed-job-groups="displayedJobGroups"
@cancel-item="onCancelItemEvent"

View File

@@ -4,7 +4,7 @@
:class="['flex', 'justify-end', 'w-full', 'pointer-events-none']"
>
<div
class="pointer-events-auto flex w-[350px] min-w-[310px] max-h-[60vh] flex-col overflow-hidden rounded-lg border font-inter transition-colors duration-200 ease-in-out"
class="pointer-events-auto flex max-h-[60vh] w-[350px] min-w-[310px] flex-col overflow-hidden rounded-lg border font-inter transition-colors duration-200 ease-in-out"
:class="containerClass"
@mouseenter="isHovered = true"
@mouseleave="isHovered = false"
@@ -15,7 +15,7 @@
v-model:selected-job-tab="selectedJobTab"
v-model:selected-workflow-filter="selectedWorkflowFilter"
v-model:selected-sort-mode="selectedSortMode"
class="flex-1 min-h-0"
class="min-h-0 flex-1"
:header-title="headerTitle"
:show-concurrent-indicator="showConcurrentIndicator"
:concurrent-workflow-count="concurrentWorkflowCount"

View File

@@ -1,11 +1,11 @@
<template>
<section
class="w-[360px] rounded-2xl border border-interface-stroke bg-interface-panel-surface text-text-primary shadow-interface font-inter"
class="w-[360px] rounded-2xl border border-interface-stroke bg-interface-panel-surface font-inter text-text-primary shadow-interface"
>
<header
class="flex items-center justify-between border-b border-interface-stroke px-4 py-4"
>
<p class="m-0 text-[14px] font-normal leading-none">
<p class="m-0 text-[14px] leading-none font-normal">
{{ t('sideToolbar.queueProgressOverlay.clearHistoryDialogTitle') }}
</p>
<Button
@@ -31,7 +31,11 @@
<footer class="flex items-center justify-end px-4 py-4">
<div class="flex items-center gap-4 leading-none">
<Button variant="muted-textonly" size="lg" @click="onCancel">
<Button
variant="muted-textonly"
size="lg"
@click="onCancel"
>
{{ t('g.cancel') }}
</Button>
<Button
@@ -39,8 +43,9 @@
size="lg"
:disabled="isClearing"
@click="onConfirm"
>{{ t('g.clear') }}</Button
>
{{ t('g.clear') }}
</Button>
</div>
</footer>
</section>

View File

@@ -72,7 +72,7 @@
<div class="relative z-1 flex items-center gap-1">
<div class="relative inline-flex items-center justify-center">
<div
class="absolute left-1/2 top-1/2 size-10 -translate-x-1/2 -translate-y-1/2"
class="absolute top-1/2 left-1/2 size-10 -translate-x-1/2 -translate-y-1/2"
@mouseenter.stop="onIconEnter"
@mouseleave.stop="onIconLeave"
/>
@@ -83,7 +83,7 @@
v-if="iconImageUrl"
:src="iconImageUrl"
class="h-full w-full object-cover"
/>
>
<i
v-else
:class="cn(iconClass, 'size-4', shouldSpin && 'animate-spin')"
@@ -93,8 +93,13 @@
</div>
<div class="relative z-1 min-w-0 flex-1">
<div class="truncate opacity-90" :title="props.title">
<slot name="primary">{{ props.title }}</slot>
<div
class="truncate opacity-90"
:title="props.title"
>
<slot name="primary">
{{ props.title }}
</slot>
</div>
</div>
@@ -159,8 +164,9 @@
variant="textonly"
size="sm"
@click.stop="emit('view')"
>{{ t('menuLabels.View') }}</Button
>
{{ t('menuLabels.View') }}
</Button>
<Button
v-if="props.showMenu !== undefined ? props.showMenu : true"
v-tooltip.top="moreTooltipConfig"
@@ -177,7 +183,9 @@
key="secondary"
class="pr-2"
>
<slot name="secondary">{{ props.rightText }}</slot>
<slot name="secondary">
{{ props.rightText }}
</slot>
</div>
</Transition>
<!-- Running job cancel button - always visible -->

View File

@@ -194,8 +194,8 @@ function handleTitleCancel() {
>
<!-- Panel Header -->
<section class="pt-1">
<div class="flex items-center justify-between pl-4 pr-3">
<h3 class="my-3.5 text-sm font-semibold line-clamp-2 cursor-default">
<div class="flex items-center justify-between pr-3 pl-4">
<h3 class="my-3.5 line-clamp-2 cursor-default text-sm font-semibold">
<template v-if="allowTitleEdit">
<EditableText
:model-value="panelTitle"
@@ -208,7 +208,7 @@ function handleTitleCancel() {
/>
<i
v-if="!isEditing"
class="icon-[lucide--pencil] size-4 text-muted-foreground ml-2 content-center relative top-[2px] hover:text-base-foreground cursor-pointer shrink-0"
class="relative top-[2px] ml-2 icon-[lucide--pencil] size-4 shrink-0 cursor-pointer content-center text-muted-foreground hover:text-base-foreground"
@click="isEditing = true"
/>
</template>
@@ -242,7 +242,7 @@ function handleTitleCancel() {
</Button>
</div>
</div>
<nav class="px-4 pb-2 pt-1 overflow-x-auto">
<nav class="overflow-x-auto px-4 pt-1 pb-2">
<TabList
:model-value="activeTab"
@update:model-value="
@@ -254,7 +254,7 @@ function handleTitleCancel() {
<Tab
v-for="tab in tabs"
:key="tab.value"
class="text-sm py-1 px-2 font-inter transition-all active:scale-95"
class="px-2 py-1 font-inter text-sm transition-all active:scale-95"
:value="tab.value"
>
{{ tab.label() }}
@@ -284,7 +284,10 @@ function handleTitleCancel() {
:nodes="selectedNodes"
:must-show-node-title="selectedGroups.length > 0"
/>
<TabInfo v-else-if="activeTab === 'info'" :nodes="selectedNodes" />
<TabInfo
v-else-if="activeTab === 'info'"
:nodes="selectedNodes"
/>
<TabSettings
v-else-if="activeTab === 'settings'"
:nodes="flattedItems"

View File

@@ -25,21 +25,21 @@ const tooltipConfig = computed(() => {
<template>
<div class="flex flex-col bg-comfy-menu-bg">
<div
class="sticky top-0 z-10 flex items-center justify-between backdrop-blur-xl bg-inherit"
class="sticky top-0 z-10 flex items-center justify-between bg-inherit backdrop-blur-xl"
>
<button
v-tooltip="tooltipConfig"
type="button"
:class="
cn(
'group min-h-12 bg-transparent border-0 outline-0 ring-0 w-full text-left flex items-center justify-between pl-4 pr-3',
'group flex min-h-12 w-full items-center justify-between border-0 bg-transparent pr-3 pl-4 text-left ring-0 outline-0',
!disabled && 'cursor-pointer'
)
"
:disabled="disabled"
@click="isCollapse = !isCollapse"
>
<span class="text-sm font-semibold line-clamp-2 flex-1">
<span class="line-clamp-2 flex-1 text-sm font-semibold">
<slot name="label">
{{ label }}
</slot>
@@ -48,7 +48,7 @@ const tooltipConfig = computed(() => {
<i
:class="
cn(
'text-muted-foreground group-hover:text-base-foreground group-has-[.subbutton:hover]:text-muted-foreground group-focus:text-base-foreground icon-[lucide--chevron-up] size-4 transition-all',
'icon-[lucide--chevron-up] size-4 text-muted-foreground transition-all group-hover:text-base-foreground group-focus:text-base-foreground group-has-[.subbutton:hover]:text-muted-foreground',
isCollapse && '-rotate-180',
disabled && 'opacity-0'
)
@@ -57,10 +57,16 @@ const tooltipConfig = computed(() => {
</button>
</div>
<TransitionCollapse>
<div v-if="isExpanded" class="pb-4">
<div
v-if="isExpanded"
class="pb-4"
>
<slot />
</div>
<slot v-else-if="enableEmptyState && disabled" name="empty">
<slot
v-else-if="enableEmptyState && disabled"
name="empty"
>
<div>
{{ $t('g.empty') }}
</div>

View File

@@ -131,8 +131,8 @@ defineExpose({
:tooltip
>
<template #label>
<div class="flex items-center gap-2 flex-1 min-w-0">
<span class="flex-1 flex items-center gap-2 min-w-0">
<div class="flex min-w-0 flex-1 items-center gap-2">
<span class="flex min-w-0 flex-1 items-center gap-2">
<span class="truncate">
<slot name="label">
{{ displayLabel }}
@@ -140,7 +140,7 @@ defineExpose({
</span>
<span
v-if="parentGroup"
class="text-xs text-muted-foreground truncate flex-1 text-right min-w-11"
class="min-w-11 flex-1 truncate text-right text-xs text-muted-foreground"
:title="parentGroup.title"
>
{{ parentGroup.title }}
@@ -150,7 +150,7 @@ defineExpose({
v-if="canShowLocateButton"
variant="textonly"
size="icon-sm"
class="subbutton shrink-0 mr-3 size-8 cursor-pointer text-muted-foreground hover:text-base-foreground"
class="subbutton mr-3 size-8 shrink-0 cursor-pointer text-muted-foreground hover:text-base-foreground"
:title="t('rightSidePanel.locateNode')"
:aria-label="t('rightSidePanel.locateNode')"
@click.stop="handleLocateNode"
@@ -160,11 +160,13 @@ defineExpose({
</div>
</template>
<template #empty><slot name="empty" /></template>
<template #empty>
<slot name="empty" />
</template>
<div
ref="widgetsContainer"
class="space-y-2 rounded-lg px-4 pt-1 relative"
class="relative space-y-2 rounded-lg px-4 pt-1"
>
<TransitionGroup name="list-scale">
<WidgetItem

View File

@@ -111,7 +111,7 @@ onBeforeUnmount(() => {
</script>
<template>
<div class="px-4 pt-1 pb-4 flex gap-2 border-b border-interface-stroke">
<div class="flex gap-2 border-b border-interface-stroke px-4 pt-1 pb-4">
<FormSearchInput
v-model="searchQuery"
:searcher
@@ -130,7 +130,7 @@ onBeforeUnmount(() => {
@update:collapse="nextTick(setDraggableState)"
>
<template #empty>
<div class="text-sm text-muted-foreground px-4 text-center py-10">
<div class="px-4 py-10 text-center text-sm text-muted-foreground">
{{
isSearching
? t('rightSidePanel.noneSearchDesc')

View File

@@ -50,17 +50,21 @@ async function searcher(query: string) {
</script>
<template>
<div class="px-4 pt-1 pb-4 flex gap-2 border-b border-interface-stroke">
<div class="flex gap-2 border-b border-interface-stroke px-4 pt-1 pb-4">
<FormSearchInput
v-model="searchQuery"
:searcher
:update-key="widgetsSectionDataList"
/>
</div>
<TransitionGroup tag="div" name="list-scale" class="relative">
<TransitionGroup
tag="div"
name="list-scale"
class="relative"
>
<div
v-if="isSearching && searchedWidgetsSectionDataList.length === 0"
class="text-sm text-muted-foreground px-4 text-center pt-5 pb-15"
class="px-4 pt-5 pb-15 text-center text-sm text-muted-foreground"
>
{{ $t('rightSidePanel.noneSearchDesc') }}
</div>

View File

@@ -59,17 +59,21 @@ const label = computed(() => {
</script>
<template>
<div class="px-4 pt-1 pb-4 flex gap-2 border-b border-interface-stroke">
<div class="flex gap-2 border-b border-interface-stroke px-4 pt-1 pb-4">
<FormSearchInput
v-model="searchQuery"
:searcher
:update-key="widgetsSectionDataList"
/>
</div>
<TransitionGroup tag="div" name="list-scale" class="relative">
<TransitionGroup
tag="div"
name="list-scale"
class="relative"
>
<div
v-if="searchedWidgetsSectionDataList.length === 0"
class="text-sm text-muted-foreground px-4 py-10 text-center"
class="px-4 py-10 text-center text-sm text-muted-foreground"
>
{{
isSearching

View File

@@ -202,7 +202,7 @@ const label = computed(() => {
</script>
<template>
<div class="px-4 pt-1 pb-4 flex gap-2 border-b border-interface-stroke">
<div class="flex gap-2 border-b border-interface-stroke px-4 pt-1 pb-4">
<FormSearchInput
v-model="searchQuery"
:searcher
@@ -226,7 +226,7 @@ const label = computed(() => {
@update:collapse="nextTick(setDraggableState)"
>
<template #empty>
<div class="text-sm text-muted-foreground px-4 text-center pt-5 pb-15">
<div class="px-4 pt-5 pb-15 text-center text-sm text-muted-foreground">
{{ t('rightSidePanel.noneSearchDesc') }}
</div>
</template>

View File

@@ -99,7 +99,7 @@ function handleToggleFavorite() {
const buttonClasses = cn([
'border-none bg-transparent',
'w-full flex items-center gap-2 rounded px-3 py-2 text-sm',
'flex w-full items-center gap-2 rounded px-3 py-2 text-sm',
'cursor-pointer transition-all hover:bg-secondary-background-hover active:scale-95'
])
</script>
@@ -107,7 +107,7 @@ const buttonClasses = cn([
<template>
<MoreButton
is-vertical
class="text-muted-foreground bg-transparent hover:text-base-foreground hover:bg-secondary-background-hover active:scale-95 transition-all"
class="bg-transparent text-muted-foreground transition-all hover:bg-secondary-background-hover hover:text-base-foreground active:scale-95"
>
<template #default="{ close }">
<button

View File

@@ -106,9 +106,9 @@ const displayLabel = customRef((track, trigger) => {
<div
:class="
cn(
'widget-item col-span-full grid grid-cols-subgrid rounded-lg group',
'widget-item group col-span-full grid grid-cols-subgrid rounded-lg',
isDraggable &&
'draggable-item !will-change-auto drag-handle cursor-grab bg-comfy-menu-bg [&.is-draggable]:cursor-grabbing outline-comfy-menu-bg [&.is-draggable]:outline-4 [&.is-draggable]:outline-offset-0 [&.is-draggable]:opacity-70'
'draggable-item drag-handle cursor-grab bg-comfy-menu-bg outline-comfy-menu-bg !will-change-auto [&.is-draggable]:cursor-grabbing [&.is-draggable]:opacity-70 [&.is-draggable]:outline-4 [&.is-draggable]:outline-offset-0'
)
"
>
@@ -116,7 +116,7 @@ const displayLabel = customRef((track, trigger) => {
<div
:class="
cn(
'min-h-8 flex items-center justify-between gap-1 mb-1.5 min-w-0',
'mb-1.5 flex min-h-8 min-w-0 items-center justify-between gap-1',
isDraggable && 'pointer-events-none'
)
"
@@ -126,7 +126,7 @@ const displayLabel = customRef((track, trigger) => {
:model-value="displayLabel"
:is-editing="isEditing"
:input-attrs="{ placeholder: widget.name }"
class="text-sm leading-8 p-0 m-0 truncate pointer-events-auto cursor-text"
class="pointer-events-auto m-0 cursor-text truncate p-0 text-sm leading-8"
@edit="displayLabel = $event"
@cancel="isEditing = false"
@click="isEditing = true"
@@ -134,11 +134,11 @@ const displayLabel = customRef((track, trigger) => {
<span
v-if="(showNodeName || hasParents) && sourceNodeName"
class="text-xs text-muted-foreground flex-1 p-0 my-0 mx-1 truncate text-right min-w-10"
class="mx-1 my-0 min-w-10 flex-1 truncate p-0 text-right text-xs text-muted-foreground"
>
{{ sourceNodeName }}
</span>
<div class="flex items-center gap-1 shrink-0 pointer-events-auto">
<div class="pointer-events-auto flex shrink-0 items-center gap-1">
<WidgetActions
v-model:label="displayLabel"
:widget="widget"
@@ -154,10 +154,10 @@ const displayLabel = customRef((track, trigger) => {
!hiddenFavoriteIndicator &&
favoritedWidgetsStore.isFavorited(favoriteNode, widget.name)
"
class="relative z-2 pointer-events-none"
class="pointer-events-none relative z-2"
>
<i
class="absolute -right-1 -top-1 pi pi-star-fill text-xs text-muted-foreground pointer-events-none"
class="pi pi-star-fill pointer-events-none absolute -top-1 -right-1 text-xs text-muted-foreground"
/>
</div>
<!-- widget content -->
@@ -173,7 +173,7 @@ const displayLabel = customRef((track, trigger) => {
<div
:class="
cn(
'pointer-events-none mt-1.5 mx-auto max-w-40 w-1/2 h-1 rounded-lg bg-transparent transition-colors duration-150',
'pointer-events-none mx-auto mt-1.5 h-1 w-1/2 max-w-40 rounded-lg bg-transparent transition-colors duration-150',
'group-hover:bg-interface-stroke group-[.is-draggable]:bg-component-node-widget-background-highlighted',
!isDraggable && 'opacity-0'
)

View File

@@ -25,7 +25,7 @@ defineProps<{
"
:class="
cn(
'text-sm text-muted-foreground truncate',
'truncate text-sm text-muted-foreground',
tooltip ? 'cursor-help' : '',
singleline ? 'flex-1' : ''
)

View File

@@ -107,14 +107,14 @@ const nodeColor = computed<NodeColorOption['name'] | null>({
<template>
<LayoutField :label="t('rightSidePanel.color')">
<div
class="bg-secondary-background border-none rounded-lg p-1 grid grid-cols-5 gap-1 justify-items-center"
class="grid grid-cols-5 justify-items-center gap-1 rounded-lg border-none bg-secondary-background p-1"
>
<button
v-for="option of colorOptions"
:key="option.name"
:class="
cn(
'size-8 rounded-lg bg-transparent border-0 outline-0 ring-0 text-left flex justify-center items-center cursor-pointer',
'flex size-8 cursor-pointer items-center justify-center rounded-lg border-0 bg-transparent text-left ring-0 outline-0',
option.name === nodeColor
? 'bg-interface-menu-component-surface-selected'
: 'hover:bg-interface-menu-component-surface-selected'

View File

@@ -125,7 +125,7 @@ function openFullSettings() {
<LayoutField :label="t('rightSidePanel.globalSettings.gridSpacing')">
<div
:class="
cn(WidgetInputBaseClass, 'flex items-center gap-2 pl-3 pr-2')
cn(WidgetInputBaseClass, 'flex items-center gap-2 pr-2 pl-3')
"
>
<Slider
@@ -189,7 +189,7 @@ function openFullSettings() {
<!-- View all settings button -->
<div
class="flex items-center justify-center p-4 border-b border-interface-stroke"
class="flex items-center justify-center border-b border-interface-stroke p-4"
>
<Button
variant="muted-textonly"

View File

@@ -239,8 +239,11 @@ onBeforeUnmount(() => {
</script>
<template>
<div v-if="activeNode" class="subgraph-edit-section flex h-full flex-col">
<div class="px-4 pb-4 pt-1 flex gap-2 border-b border-interface-stroke">
<div
v-if="activeNode"
class="subgraph-edit-section flex h-full flex-col"
>
<div class="flex gap-2 border-b border-interface-stroke px-4 pt-1 pb-4">
<FormSearchInput v-model="searchQuery" />
</div>
@@ -251,7 +254,7 @@ onBeforeUnmount(() => {
filteredActive.length === 0 &&
filteredCandidates.length === 0
"
class="text-sm text-muted-foreground px-4 py-10 text-center"
class="px-4 py-10 text-center text-sm text-muted-foreground"
>
{{ $t('rightSidePanel.noneSearchDesc') }}
</div>
@@ -261,19 +264,21 @@ onBeforeUnmount(() => {
class="flex flex-col border-b border-interface-stroke"
>
<div
class="sticky top-0 z-10 flex items-center justify-between backdrop-blur-xl min-h-12 px-4"
class="sticky top-0 z-10 flex min-h-12 items-center justify-between px-4 backdrop-blur-xl"
>
<div class="text-sm font-semibold uppercase line-clamp-1">
<div class="line-clamp-1 text-sm font-semibold uppercase">
{{ $t('subgraphStore.shown') }}
</div>
<a
class="cursor-pointer text-right text-xs font-normal text-text-secondary hover:text-azure-600 whitespace-nowrap"
class="cursor-pointer text-right text-xs font-normal whitespace-nowrap text-text-secondary hover:text-azure-600"
@click.stop="hideAll"
>
{{ $t('subgraphStore.hideAll') }}</a
>
{{ $t('subgraphStore.hideAll') }}</a>
</div>
<div ref="draggableItems" class="pb-2 px-2 space-y-0.5 mt-0.5">
<div
ref="draggableItems"
class="mt-0.5 space-y-0.5 px-2 pb-2"
>
<SubgraphNodeWidget
v-for="[node, widget] in filteredActive"
:key="toKey([node, widget])"
@@ -293,19 +298,18 @@ onBeforeUnmount(() => {
class="flex flex-col border-b border-interface-stroke"
>
<div
class="sticky top-0 z-10 flex items-center justify-between backdrop-blur-xl min-h-12 px-4"
class="sticky top-0 z-10 flex min-h-12 items-center justify-between px-4 backdrop-blur-xl"
>
<div class="text-sm font-semibold uppercase line-clamp-1">
<div class="line-clamp-1 text-sm font-semibold uppercase">
{{ $t('subgraphStore.hidden') }}
</div>
<a
class="cursor-pointer text-right text-xs font-normal text-text-secondary hover:text-azure-600 whitespace-nowrap"
class="cursor-pointer text-right text-xs font-normal whitespace-nowrap text-text-secondary hover:text-azure-600"
@click.stop="showAll"
>
{{ $t('subgraphStore.showAll') }}</a
>
{{ $t('subgraphStore.showAll') }}</a>
</div>
<div class="pb-2 px-2 space-y-0.5 mt-0.5">
<div class="mt-0.5 space-y-0.5 px-2 pb-2">
<SubgraphNodeWidget
v-for="[node, widget] in filteredCandidates"
:key="toKey([node, widget])"

View File

@@ -27,19 +27,21 @@ function getIcon() {
<div
:class="
cn(
'flex py-1 px-2 break-all rounded items-center gap-1',
'flex items-center gap-1 rounded px-2 py-1 break-all',
'bg-node-component-surface',
props.isDraggable &&
'draggable-item drag-handle cursor-grab [&.is-draggable]:cursor-grabbing hover:ring-1 ring-accent-background',
'draggable-item drag-handle cursor-grab ring-accent-background hover:ring-1 [&.is-draggable]:cursor-grabbing',
props.class
)
"
>
<div class="pointer-events-none flex-1">
<div class="text-xs text-text-secondary line-clamp-1">
<div class="line-clamp-1 text-xs text-text-secondary">
{{ nodeTitle }}
</div>
<div class="text-sm line-clamp-1 leading-8">{{ widgetName }}</div>
<div class="line-clamp-1 text-sm leading-8">
{{ widgetName }}
</div>
</div>
<Button
variant="muted-textonly"
@@ -51,7 +53,7 @@ function getIcon() {
</Button>
<div
v-if="isDraggable"
class="size-4 pointer-events-none icon-[lucide--grip-vertical]"
class="pointer-events-none icon-[lucide--grip-vertical] size-4"
/>
</div>
</template>

View File

@@ -17,7 +17,12 @@
/>
</div>
<div class="_footer">
<Button type="button" @click="submit">{{ $t('g.add') }}</Button>
<Button
type="button"
@click="submit"
>
{{ $t('g.add') }}
</Button>
</div>
</template>
@@ -76,6 +81,6 @@ const submit = () => {
}
._footer {
@apply flex flex-col pt-4 items-end;
@apply flex flex-col items-end pt-4;
}
</style>

View File

@@ -7,7 +7,7 @@ import { useCommandStore } from '@/stores/commandStore'
const canvasStore = useCanvasStore()
</script>
<template>
<div class="p-1 bg-secondary-background rounded-lg w-10">
<div class="w-10 rounded-lg bg-secondary-background p-1">
<Button
size="icon"
:title="t('linearMode.linearMode')"

View File

@@ -14,10 +14,13 @@
:class="
isOverflowing
? 'side-tool-bar-container overflow-y-auto'
: 'flex flex-col h-full'
: 'flex h-full flex-col'
"
>
<div ref="topToolbarRef" :class="groupClasses">
<div
ref="topToolbarRef"
:class="groupClasses"
>
<ComfyMenuButton />
<SidebarIcon
v-for="tab in tabs"
@@ -35,12 +38,19 @@
<SidebarTemplatesButton />
</div>
<div ref="bottomToolbarRef" class="mt-auto" :class="groupClasses">
<div
ref="bottomToolbarRef"
class="mt-auto"
:class="groupClasses"
>
<SidebarLogoutIcon
v-if="userStore.isMultiUserServer"
:is-small="isSmall"
/>
<SidebarHelpCenterIcon v-if="!isIntegratedTabBar" :is-small="isSmall" />
<SidebarHelpCenterIcon
v-if="!isIntegratedTabBar"
:is-small="isSmall"
/>
<SidebarBottomPanelToggleButton :is-small="isSmall" />
<SidebarShortcutsToggleButton :is-small="isSmall" />
<SidebarSettingsButton :is-small="isSmall" />
@@ -158,8 +168,8 @@ const getTabTooltipSuffix = (tab: SidebarTabExtension) => {
const isOverflowing = ref(false)
const groupClasses = computed(() =>
cn(
'sidebar-item-group flex flex-col items-center overflow-hidden flex-shrink-0',
!isConnected.value && 'rounded-lg shadow-interface pointer-events-auto'
'sidebar-item-group flex flex-shrink-0 flex-col items-center overflow-hidden',
!isConnected.value && 'pointer-events-auto rounded-lg shadow-interface'
)
)

View File

@@ -17,12 +17,19 @@
>
<div class="side-bar-button-content">
<slot name="icon">
<OverlayBadge v-if="shouldShowBadge" :value="overlayValue">
<OverlayBadge
v-if="shouldShowBadge"
:value="overlayValue"
>
<i
v-if="typeof icon === 'string'"
:class="icon + ' side-bar-button-icon'"
/>
<component :is="icon" v-else class="side-bar-button-icon" />
<component
:is="icon"
v-else
class="side-bar-button-icon"
/>
</OverlayBadge>
<i
v-else-if="typeof icon === 'string'"
@@ -34,7 +41,10 @@
class="side-bar-button-icon"
/>
</slot>
<span v-if="label && !isSmall" class="side-bar-button-label">{{
<span
v-if="label && !isSmall"
class="side-bar-button-label"
>{{
t(label)
}}</span>
</div>
@@ -117,7 +127,7 @@ const computedTooltip = computed(() => t(tooltip) + tooltipSuffix)
}
.side-bar-button-label {
@apply text-[10px] text-center;
@apply text-center text-[10px];
line-height: 1;
}

View File

@@ -25,7 +25,10 @@
@mouseleave="onJobLeave(job.id)"
@click.stop
>
<template v-if="hoveredJobId === job.id" #actions>
<template
v-if="hoveredJobId === job.id"
#actions
>
<Button
v-if="canCancelJob"
:variant="cancelAction.variant"
@@ -33,7 +36,10 @@
:aria-label="cancelAction.label"
@click.stop="runCancelJob()"
>
<i :class="cancelAction.icon" class="size-4" />
<i
:class="cancelAction.icon"
class="size-4"
/>
</Button>
</template>
</AssetsListItem>
@@ -44,7 +50,7 @@
:class="cn('px-2', activeJobItems.length && 'mt-2')"
>
<div
class="flex items-center py-2 text-sm font-normal leading-normal text-muted-foreground font-inter"
class="flex items-center py-2 font-inter text-sm leading-normal font-normal text-muted-foreground"
>
{{ t('sideToolbar.generatedAssetsHeader') }}
</div>
@@ -79,7 +85,10 @@
@contextmenu.prevent.stop="emit('context-menu', $event, item.asset)"
@click.stop="emit('select-asset', item.asset)"
>
<template v-if="hoveredAssetId === item.asset.id" #actions>
<template
v-if="hoveredAssetId === item.asset.id"
#actions
>
<Button
variant="secondary"
size="icon"
@@ -194,7 +203,7 @@ function getAssetCardClass(selected: boolean): string {
'w-full text-text-primary transition-colors hover:bg-secondary-background-hover',
'cursor-pointer',
selected &&
'bg-secondary-background-hover ring-1 ring-inset ring-modal-card-border-highlighted'
'bg-secondary-background-hover ring-1 ring-modal-card-border-highlighted ring-inset'
)
}

View File

@@ -15,7 +15,7 @@
role="button"
@click="copyJobId"
>
<i class="icon-[lucide--copy] text-sm"></i>
<i class="icon-[lucide--copy] text-sm" />
</button>
</div>
<div>
@@ -25,19 +25,39 @@
</template>
<template #tool-buttons>
<!-- Normal Tab View -->
<TabList v-if="!isInFolderView" v-model="activeTab">
<Tab class="font-inter" value="output">{{
<TabList
v-if="!isInFolderView"
v-model="activeTab"
>
<Tab
class="font-inter"
value="output"
>
{{
$t('sideToolbar.labels.generated')
}}</Tab>
<Tab class="font-inter" value="input">{{
}}
</Tab>
<Tab
class="font-inter"
value="input"
>
{{
$t('sideToolbar.labels.imported')
}}</Tab>
}}
</Tab>
</TabList>
</template>
<template #header>
<!-- Job Detail View Header -->
<div v-if="isInFolderView" class="px-2 2xl:px-4">
<Button variant="secondary" size="lg" @click="exitFolderView">
<div
v-if="isInFolderView"
class="px-2 2xl:px-4"
>
<Button
variant="secondary"
size="lg"
@click="exitFolderView"
>
<i class="icon-[lucide--arrow-left] size-4" />
<span>{{ $t('sideToolbar.backToAssets') }}</span>
</Button>
@@ -49,7 +69,7 @@
v-model:sort-by="sortBy"
v-model:view-mode="viewMode"
v-model:media-type-filters="mediaTypeFilters"
class="pb-1 px-2 2xl:px-4"
class="px-2 pb-1 2xl:px-4"
:show-generation-time-sort="activeTab === 'output'"
/>
<div
@@ -76,7 +96,11 @@
</Button>
</div>
</div>
<Divider v-else type="dashed" class="my-2" />
<Divider
v-else
type="dashed"
class="my-2"
/>
</template>
<template #body>
<div v-if="showLoadingState">
@@ -95,7 +119,11 @@
:message="$t('sideToolbar.noFilesFoundMessage')"
/>
</div>
<div v-else class="relative size-full" @click="handleEmptySpaceClick">
<div
v-else
class="relative size-full"
@click="handleEmptySpaceClick"
>
<AssetsSidebarListView
v-if="isListView"
:assets="displayAssets"
@@ -134,10 +162,13 @@
<div
v-if="hasSelection"
ref="footerRef"
class="flex gap-1 h-18 w-full items-center justify-between"
class="flex h-18 w-full items-center justify-between gap-1"
>
<div class="flex-1 pl-4">
<div ref="selectionCountButtonRef" class="inline-flex w-48">
<div
ref="selectionCountButtonRef"
class="inline-flex w-48"
>
<Button
variant="secondary"
:class="cn(isCompact && 'text-left')"
@@ -153,7 +184,7 @@
</Button>
</div>
</div>
<div class="flex shrink gap-2 pr-4 items-center-safe justify-end-safe">
<div class="flex shrink items-center-safe justify-end-safe gap-2 pr-4">
<template v-if="isCompact">
<!-- Compact mode: Icon only -->
<Button
@@ -163,7 +194,10 @@
>
<i class="icon-[lucide--trash-2] size-4" />
</Button>
<Button size="icon" @click="handleDownloadSelected">
<Button
size="icon"
@click="handleDownloadSelected"
>
<i class="icon-[lucide--download] size-4" />
</Button>
</template>
@@ -177,7 +211,10 @@
<span>{{ $t('mediaAsset.selection.deleteSelected') }}</span>
<i class="icon-[lucide--trash-2] size-4" />
</Button>
<Button variant="secondary" @click="handleDownloadSelected">
<Button
variant="secondary"
@click="handleDownloadSelected"
>
<span>{{ $t('mediaAsset.selection.downloadSelected') }}</span>
<i class="icon-[lucide--download] size-4" />
</Button>

View File

@@ -5,17 +5,20 @@
>
<div class="comfy-vue-side-bar-header flex flex-col gap-2">
<Toolbar
class="min-h-16 bg-transparent rounded-none border-x-0 border-t-0 px-2 2xl:px-4"
class="min-h-16 rounded-none border-x-0 border-t-0 bg-transparent px-2 2xl:px-4"
>
<template #start>
<span class="truncate font-bold" :title="props.title">
<span
class="truncate font-bold"
:title="props.title"
>
{{ props.title }}
</span>
<slot name="alt-title" />
</template>
<template #end>
<div
class="touch:w-auto touch:opacity-100 flex flex-row overflow-hidden 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"
class="flex flex-row overflow-hidden 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 touch:w-auto touch:opacity-100"
>
<slot name="tool-buttons" />
</div>

View File

@@ -32,12 +32,12 @@ const isActive = computed(() => currentValue?.value === value)
const tabClasses = computed(() => {
return cn(
// Base styles from TextButton
'flex items-center justify-center shrink-0',
'px-2.5 py-2 text-sm rounded-lg cursor-pointer transition-all duration-200',
'outline-hidden border-none',
'flex shrink-0 items-center justify-center',
'cursor-pointer rounded-lg px-2.5 py-2 text-sm transition-all duration-200',
'border-none outline-hidden',
// State styles with semantic tokens
isActive.value
? 'bg-interface-menu-component-surface-hovered text-text-primary text-bold'
? 'text-bold bg-interface-menu-component-surface-hovered text-text-primary'
: 'bg-transparent text-text-secondary hover:bg-button-hover-surface focus:bg-button-hover-surface'
)
})

View File

@@ -11,14 +11,20 @@
<div
:class="
cn(
'flex items-center gap-1 rounded-full hover:bg-interface-button-hover-surface justify-center',
compact && 'size-full aspect-square'
'flex items-center justify-center gap-1 rounded-full hover:bg-interface-button-hover-surface',
compact && 'aspect-square size-full'
)
"
>
<UserAvatar :photo-url="photoURL" :class="compact && 'size-full'" />
<UserAvatar
:photo-url="photoURL"
:class="compact && 'size-full'"
/>
<i v-if="showArrow" class="icon-[lucide--chevron-down] size-3 px-1" />
<i
v-if="showArrow"
class="icon-[lucide--chevron-down] size-3 px-1"
/>
</div>
</Button>

View File

@@ -1,10 +1,10 @@
<!-- A popover that shows current user information and actions -->
<template>
<div
class="current-user-popover w-80 -m-3 p-2 rounded-lg border border-border-default bg-base-background shadow-[1px_1px_8px_0_rgba(0,0,0,0.4)]"
class="current-user-popover -m-3 w-80 rounded-lg border border-border-default bg-base-background p-2 shadow-[1px_1px_8px_0_rgba(0,0,0,0.4)]"
>
<!-- User Info Section -->
<div class="flex flex-col items-center px-0 py-3 mb-4">
<div class="mb-4 flex flex-col items-center px-0 py-3">
<UserAvatar
class="mb-1"
:photo-url="userPhotoUrl"
@@ -18,32 +18,41 @@
<h3 class="my-0 mb-1 truncate text-base font-bold text-base-foreground">
{{ userDisplayName || $t('g.user') }}
</h3>
<p v-if="userEmail" class="my-0 truncate text-sm text-muted">
<p
v-if="userEmail"
class="my-0 truncate text-sm text-muted"
>
{{ userEmail }}
</p>
<span
v-if="subscriptionTierName"
class="my-0 text-xs text-foreground bg-secondary-background-hover rounded-full uppercase px-2 py-0.5 font-bold mt-2"
class="text-foreground my-0 mt-2 rounded-full bg-secondary-background-hover px-2 py-0.5 text-xs font-bold uppercase"
>
{{ subscriptionTierName }}
</span>
</div>
<!-- Credits Section -->
<div v-if="isActiveSubscription" class="flex items-center gap-2 px-4 py-2">
<i class="icon-[lucide--component] text-amber-400 text-sm" />
<div
v-if="isActiveSubscription"
class="flex items-center gap-2 px-4 py-2"
>
<i class="icon-[lucide--component] text-sm text-amber-400" />
<Skeleton
v-if="authStore.isFetchingBalance"
width="4rem"
height="1.25rem"
class="w-full"
/>
<span v-else class="text-base font-semibold text-base-foreground">{{
<span
v-else
class="text-base font-semibold text-base-foreground"
>{{
formattedBalance
}}</span>
<i
v-tooltip="{ value: $t('credits.unified.tooltip'), showDelay: 300 }"
class="icon-[lucide--circle-help] cursor-help text-base text-muted-foreground mr-auto"
class="mr-auto icon-[lucide--circle-help] cursor-help text-base text-muted-foreground"
/>
<Button
variant="secondary"
@@ -56,7 +65,10 @@
</Button>
</div>
<div v-else class="flex justify-center px-4">
<div
v-else
class="flex justify-center px-4"
>
<SubscribeButton
:fluid="false"
:label="$t('subscription.subscribeToComfyCloud')"
@@ -66,32 +78,32 @@
/>
</div>
<Divider class="my-2 mx-0" />
<Divider class="mx-0 my-2" />
<div
v-if="isActiveSubscription"
class="flex items-center gap-2 px-4 py-2 cursor-pointer hover:bg-secondary-background-hover"
class="flex cursor-pointer items-center gap-2 px-4 py-2 hover:bg-secondary-background-hover"
data-testid="partner-nodes-menu-item"
@click="handleOpenPartnerNodesInfo"
>
<i class="icon-[lucide--tag] text-muted-foreground text-sm" />
<span class="text-sm text-base-foreground flex-1">{{
<i class="icon-[lucide--tag] text-sm text-muted-foreground" />
<span class="flex-1 text-sm text-base-foreground">{{
$t('subscription.partnerNodesCredits')
}}</span>
</div>
<div
class="flex items-center gap-2 px-4 py-2 cursor-pointer hover:bg-secondary-background-hover"
class="flex cursor-pointer items-center gap-2 px-4 py-2 hover:bg-secondary-background-hover"
data-testid="plans-pricing-menu-item"
@click="handleOpenPlansAndPricing"
>
<i class="icon-[lucide--receipt-text] text-muted-foreground text-sm" />
<span class="text-sm text-base-foreground flex-1">{{
<i class="icon-[lucide--receipt-text] text-sm text-muted-foreground" />
<span class="flex-1 text-sm text-base-foreground">{{
$t('subscription.plansAndPricing')
}}</span>
<span
v-if="canUpgrade"
class="text-xs font-bold text-base-background bg-base-foreground px-1.5 py-0.5 rounded-full"
class="rounded-full bg-base-foreground px-1.5 py-0.5 text-xs font-bold text-base-background"
>
{{ $t('subscription.upgrade') }}
</span>
@@ -99,36 +111,36 @@
<div
v-if="isActiveSubscription"
class="flex items-center gap-2 px-4 py-2 cursor-pointer hover:bg-secondary-background-hover"
class="flex cursor-pointer items-center gap-2 px-4 py-2 hover:bg-secondary-background-hover"
data-testid="manage-plan-menu-item"
@click="handleOpenPlanAndCreditsSettings"
>
<i class="icon-[lucide--file-text] text-muted-foreground text-sm" />
<span class="text-sm text-base-foreground flex-1">{{
<i class="icon-[lucide--file-text] text-sm text-muted-foreground" />
<span class="flex-1 text-sm text-base-foreground">{{
$t('subscription.managePlan')
}}</span>
</div>
<div
class="flex items-center gap-2 px-4 py-2 cursor-pointer hover:bg-secondary-background-hover"
class="flex cursor-pointer items-center gap-2 px-4 py-2 hover:bg-secondary-background-hover"
data-testid="user-settings-menu-item"
@click="handleOpenUserSettings"
>
<i class="icon-[lucide--settings-2] text-muted-foreground text-sm" />
<span class="text-sm text-base-foreground flex-1">{{
<i class="icon-[lucide--settings-2] text-sm text-muted-foreground" />
<span class="flex-1 text-sm text-base-foreground">{{
$t('userSettings.accountSettings')
}}</span>
</div>
<Divider class="my-2 mx-0" />
<Divider class="mx-0 my-2" />
<div
class="flex items-center gap-2 px-4 py-2 cursor-pointer hover:bg-secondary-background-hover"
class="flex cursor-pointer items-center gap-2 px-4 py-2 hover:bg-secondary-background-hover"
data-testid="logout-menu-item"
@click="handleLogout"
>
<i class="icon-[lucide--log-out] text-muted-foreground text-sm" />
<span class="text-sm text-base-foreground flex-1">{{
<i class="icon-[lucide--log-out] text-sm text-muted-foreground" />
<span class="flex-1 text-sm text-base-foreground">{{
$t('auth.signOut.signOut')
}}</span>
</div>

View File

@@ -3,7 +3,7 @@
v-if="!isLoggedIn"
variant="textonly"
size="icon"
:class="cn('group rounded-full text-base-foreground p-0', className)"
:class="cn('group rounded-full p-0 text-base-foreground', className)"
:aria-label="t('g.login')"
@click="handleSignIn()"
@mouseenter="showPopover"
@@ -22,13 +22,14 @@
@mouseover="cancelHidePopover"
>
<div>
<div class="mb-1">{{ t('auth.loginButton.tooltipHelp') }}</div>
<div class="mb-1">
{{ t('auth.loginButton.tooltipHelp') }}
</div>
<a
:href="apiNodesOverviewUrl"
target="_blank"
class="text-neutral-500 hover:text-primary"
>{{ t('auth.loginButton.tooltipLearnMore') }}</a
>
>{{ t('auth.loginButton.tooltipLearnMore') }}</a>
</div>
</Popover>
</template>

View File

@@ -4,8 +4,10 @@
variant="textonly"
@click="toggleHelpCenter"
>
<div class="not-md:hidden">{{ $t('menu.helpAndFeedback') }}</div>
<i class="icon-[lucide--circle-help] ml-0.5" />
<div class="not-md:hidden">
{{ $t('menu.helpAndFeedback') }}
</div>
<i class="ml-0.5 icon-[lucide--circle-help]" />
<span
v-if="shouldShowRedDot"
class="absolute top-[7px] right-[7px] size-1.5 rounded-full bg-[#ff3b30]"

View File

@@ -18,7 +18,11 @@
>
{{ badge.label }}
</div>
<div v-else class="size-2 shrink-0 rounded-full" :class="dotClasses" />
<div
v-else
class="size-2 shrink-0 rounded-full"
:class="dotClasses"
/>
<Popover
ref="popover"
append-to="body"
@@ -37,8 +41,13 @@
>
{{ badge.label }}
</div>
<div class="text-sm font-inter">{{ badge.text }}</div>
<div v-if="badge.tooltip" class="text-xs">
<div class="font-inter text-sm">
{{ badge.text }}
</div>
<div
v-if="badge.tooltip"
class="text-xs"
>
{{ badge.tooltip }}
</div>
</div>
@@ -90,8 +99,13 @@
>
{{ badge.label }}
</div>
<div class="text-sm font-inter">{{ badge.text }}</div>
<div v-if="badge.tooltip" class="text-xs">
<div class="font-inter text-sm">
{{ badge.text }}
</div>
<div
v-if="badge.tooltip"
class="text-xs"
>
{{ badge.tooltip }}
</div>
</div>
@@ -117,7 +131,10 @@
>
{{ badge.label }}
</div>
<div class="font-inter text-sm" :class="textClasses">
<div
class="font-inter text-sm"
:class="textClasses"
>
{{ badge.text }}
</div>
</div>

View File

@@ -2,7 +2,7 @@
<div>
<Button
v-tooltip="{ value: $t('g.moreWorkflows'), showDelay: 300 }"
class="rounded-none h-full w-auto aspect-square"
class="aspect-square h-full w-auto rounded-none"
variant="muted-textonly"
size="icon"
:aria-label="$t('g.moreWorkflows')"

View File

@@ -2,7 +2,7 @@
<div
ref="positionRef"
class="absolute bottom-0 left-1/2 -translate-x-1/2"
></div>
/>
<Popover
ref="popoverRef"
append-to="body"
@@ -24,7 +24,7 @@
:src="thumbnailUrl"
class="block h-[200px] rounded-lg object-cover p-2"
:style="{ width: `${POPOVER_WIDTH}px` }"
/>
>
</div>
<div class="workflow-preview-footer">
<span class="workflow-preview-name">{{ workflowFilename }}</span>
@@ -143,7 +143,7 @@ defineExpose({
@reference '../../assets/css/style.css';
.workflow-preview-content {
@apply flex flex-col rounded-xl overflow-hidden;
@apply flex flex-col overflow-hidden rounded-xl;
max-width: var(--popover-width);
background-color: var(--comfy-menu-bg);
color: var(--fg-color);
@@ -163,11 +163,11 @@ defineExpose({
}
.workflow-preview-footer {
@apply pt-1 pb-2 px-3;
@apply px-3 pt-1 pb-2;
}
.workflow-preview-name {
@apply block text-sm font-medium overflow-hidden text-ellipsis whitespace-nowrap;
@apply block overflow-hidden text-sm font-medium text-ellipsis whitespace-nowrap;
color: var(--fg-color);
}
</style>
@@ -178,7 +178,7 @@ defineExpose({
.workflow-popover-fade {
--p-popover-background: transparent;
--p-popover-content-padding: 0;
@apply bg-transparent rounded-xl shadow-lg;
@apply rounded-xl bg-transparent shadow-lg;
transition: opacity 0.15s ease-out !important;
}

View File

@@ -8,7 +8,7 @@
v-if="showOverflowArrows"
variant="muted-textonly"
size="icon"
class="overflow-arrow overflow-arrow-left h-full w-auto aspect-square"
class="overflow-arrow overflow-arrow-left aspect-square h-full w-auto"
:aria-label="$t('g.scrollLeft')"
:disabled="!leftArrowEnabled"
@mousedown="whileMouseDown($event, () => scroll(-1))"
@@ -45,7 +45,7 @@
v-if="showOverflowArrows"
variant="muted-textonly"
size="icon"
class="overflow-arrow overflow-arrow-right h-full w-auto aspect-square"
class="overflow-arrow overflow-arrow-right aspect-square h-full w-auto"
:aria-label="$t('g.scrollRight')"
:disabled="!rightArrowEnabled"
@mousedown="whileMouseDown($event, () => scroll(1))"
@@ -59,7 +59,7 @@
/>
<Button
v-tooltip="{ value: $t('sideToolbar.newBlankWorkflow'), showDelay: 300 }"
class="new-blank-workflow-button no-drag shrink-0 rounded-none h-full w-auto aspect-square"
class="new-blank-workflow-button no-drag aspect-square h-full w-auto shrink-0 rounded-none"
variant="muted-textonly"
size="icon"
:aria-label="$t('sideToolbar.newBlankWorkflow')"
@@ -78,15 +78,30 @@
compact
class="shrink-0 p-1"
/>
<LoginButton v-else-if="isDesktop" class="p-1" />
<LoginButton
v-else-if="isDesktop"
class="p-1"
/>
</div>
<ContextMenu ref="menu" :model="contextMenuItems">
<ContextMenu
ref="menu"
:model="contextMenuItems"
>
<template #itemicon="{ item }">
<OverlayIcon v-if="item.overlayIcon" v-bind="item.overlayIcon" />
<i v-else-if="item.icon" :class="item.icon" />
<OverlayIcon
v-if="item.overlayIcon"
v-bind="item.overlayIcon"
/>
<i
v-else-if="item.icon"
:class="item.icon"
/>
</template>
</ContextMenu>
<div v-if="isDesktop" class="window-actions-spacer app-drag shrink-0" />
<div
v-if="isDesktop"
class="window-actions-spacer app-drag shrink-0"
/>
</div>
</template>
@@ -383,13 +398,13 @@ onUpdated(() => {
}
:deep(.p-togglebutton) {
@apply p-0 bg-transparent rounded-none shrink relative border-0 border-r border-solid;
@apply relative shrink rounded-none border-0 border-r border-solid bg-transparent p-0;
border-right-color: var(--border-color);
min-width: 90px;
}
.overflow-arrow {
@apply px-2 rounded-none;
@apply rounded-none px-2;
}
.overflow-arrow[disabled] {
@@ -418,7 +433,7 @@ onUpdated(() => {
}
:deep(.p-togglebutton.p-togglebutton-checked) {
@apply border-b border-solid h-full;
@apply h-full border-b border-solid;
border-bottom-color: var(--p-button-text-primary-color);
}
@@ -446,7 +461,7 @@ onUpdated(() => {
}
:deep(.p-selectbutton) {
@apply rounded-none h-full;
@apply h-full rounded-none;
}
.workflow-tabs-container-desktop {

View File

@@ -36,21 +36,21 @@ defineProps<{
:side-offset="5"
:collision-padding="10"
v-bind="$attrs"
class="rounded-lg p-2 bg-base-background shadow-sm border border-border-subtle will-change-[transform,opacity] data-[state=open]:data-[side=top]:animate-slideDownAndFade data-[state=open]:data-[side=right]:animate-slideLeftAndFade data-[state=open]:data-[side=bottom]:animate-slideUpAndFade data-[state=open]:data-[side=left]:animate-slideRightAndFade"
class="data-[state=open]:data-[side=top]:animate-slideDownAndFade data-[state=open]:data-[side=right]:animate-slideLeftAndFade data-[state=open]:data-[side=bottom]:animate-slideUpAndFade data-[state=open]:data-[side=left]:animate-slideRightAndFade rounded-lg border border-border-subtle bg-base-background p-2 shadow-sm will-change-[transform,opacity]"
>
<slot>
<div class="flex flex-col p-1">
<section
v-for="(entryGroup, index) in entries ?? []"
:key="index"
class="flex flex-col border-b-2 last:border-none border-border-subtle"
class="flex flex-col border-b-2 border-border-subtle last:border-none"
>
<div
v-for="{ label, action, icon } in entryGroup"
:key="label"
:class="
cn(
'flex flex-row gap-4 p-2 rounded-sm my-1',
'my-1 flex flex-row gap-4 rounded-sm p-2',
action &&
'cursor-pointer hover:bg-secondary-background-hover'
)
@@ -63,7 +63,10 @@ defineProps<{
}
"
>
<i v-if="icon" :class="icon" />
<i
v-if="icon"
:class="icon"
/>
{{ label }}
</div>
</section>

View File

@@ -20,10 +20,17 @@ whenever(feedbackRef, () => {
<template>
<Popover>
<template #button>
<Button variant="inverted" class="rounded-full size-12">
<Button
variant="inverted"
class="size-12 rounded-full"
>
<i class="icon-[lucide--circle-question-mark] size-6" />
</Button>
</template>
<div ref="feedbackRef" data-tf-auto-resize :data-tf-widget />
<div
ref="feedbackRef"
data-tf-auto-resize
:data-tf-widget
/>
</Popover>
</template>

View File

@@ -47,7 +47,7 @@ const transform = computed(() => {
<template>
<div
ref="zoomPane"
class="contain-size place-content-center"
class="place-content-center contain-size"
@wheel="handleWheel"
@pointerdown.prevent="handleDown"
@pointermove="handleMove"

View File

@@ -2,11 +2,11 @@ import type { VariantProps } from 'cva'
import { cva } from 'cva'
export const buttonVariants = cva({
base: 'relative inline-flex items-center justify-center gap-2 cursor-pointer whitespace-nowrap appearance-none border-none rounded-md text-sm font-medium font-inter transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0',
base: 'focus-visible:ring-ring relative inline-flex cursor-pointer appearance-none items-center justify-center gap-2 rounded-md border-none font-inter text-sm font-medium whitespace-nowrap transition-colors focus-visible:ring-1 focus-visible:outline-none disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0',
variants: {
variant: {
secondary:
'bg-secondary-background text-secondary-foreground hover:bg-secondary-background-hover',
'text-secondary-foreground bg-secondary-background hover:bg-secondary-background-hover',
primary:
'bg-primary-background text-base-foreground hover:bg-primary-background-hover',
inverted:
@@ -14,11 +14,11 @@ export const buttonVariants = cva({
destructive:
'bg-destructive-background text-base-foreground hover:bg-destructive-background-hover',
textonly:
'text-base-foreground bg-transparent hover:bg-secondary-background-hover',
'bg-transparent text-base-foreground hover:bg-secondary-background-hover',
'muted-textonly':
'text-muted-foreground bg-transparent hover:bg-secondary-background-hover',
'bg-transparent text-muted-foreground hover:bg-secondary-background-hover',
'destructive-textonly':
'text-destructive-background bg-transparent hover:bg-destructive-background/10',
'bg-transparent text-destructive-background hover:bg-destructive-background/10',
'overlay-white': 'bg-white text-gray-600 hover:bg-white/90'
},
size: {

View File

@@ -50,7 +50,7 @@ const forwarded = useForwardPropsEmits(delegatedProps, emits)
data-slot="slider-track"
:class="
cn(
'bg-node-stroke relative grow overflow-hidden rounded-full',
'relative grow overflow-hidden rounded-full bg-node-stroke',
'cursor-pointer overflow-visible',
`before:absolute before:-inset-2 before:block before:bg-transparent`,
'data-[orientation=horizontal]:h-0.5 data-[orientation=horizontal]:w-full',
@@ -70,9 +70,9 @@ const forwarded = useForwardPropsEmits(delegatedProps, emits)
data-slot="slider-thumb"
:class="
cn(
'bg-node-component-surface-highlight ring-node-component-surface-selected block size-3.5 shrink-0 rounded-full shadow-sm transition-[color,box-shadow]',
'block size-3.5 shrink-0 rounded-full bg-node-component-surface-highlight shadow-sm ring-node-component-surface-selected transition-[color,box-shadow]',
'cursor-grab',
'before:absolute before:-inset-1 before:block before:bg-transparent before:rounded-full',
'before:absolute before:-inset-1 before:block before:rounded-full before:bg-transparent',
'hover:ring-2 focus-visible:ring-2 focus-visible:outline-hidden disabled:pointer-events-none disabled:opacity-50',
{ 'cursor-grabbing': pressed }
)

View File

@@ -3,14 +3,14 @@
:for="inputId"
:class="
cn(
'flex h-10 cursor-text items-center rounded-lg bg-secondary-background text-secondary-foreground hover:bg-secondary-background-hover focus-within:ring-1 focus-within:ring-secondary-foreground',
disabled && 'opacity-50 pointer-events-none'
'text-secondary-foreground focus-within:ring-secondary-foreground flex h-10 cursor-text items-center rounded-lg bg-secondary-background focus-within:ring-1 hover:bg-secondary-background-hover',
disabled && 'pointer-events-none opacity-50'
)
"
>
<button
type="button"
class="flex h-full w-8 cursor-pointer items-center justify-center rounded-l-lg border-none bg-transparent text-muted-foreground transition-colors hover:text-base-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-inset focus-visible:ring-secondary-foreground disabled:opacity-30"
class="focus-visible:ring-secondary-foreground flex h-full w-8 cursor-pointer items-center justify-center rounded-l-lg border-none bg-transparent text-muted-foreground transition-colors hover:text-base-foreground focus-visible:ring-1 focus-visible:outline-none focus-visible:ring-inset disabled:opacity-30"
:disabled="disabled || modelValue <= min"
:aria-label="$t('g.decrement')"
@click="handleStep(-1)"
@@ -28,17 +28,17 @@
type="text"
inputmode="numeric"
:style="{ width: `${inputWidth}ch` }"
class="min-w-0 rounded border-none bg-transparent text-center text-base-foreground font-medium text-lg focus-visible:outline-none"
class="min-w-0 rounded border-none bg-transparent text-center text-lg font-medium text-base-foreground focus-visible:outline-none"
:disabled="disabled"
@input="handleInputChange"
@blur="handleInputBlur"
@focus="handleInputFocus"
/>
>
<slot name="suffix" />
</div>
<button
type="button"
class="flex h-full w-8 cursor-pointer items-center justify-center rounded-r-lg border-none bg-transparent text-muted-foreground transition-colors hover:text-base-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-inset focus-visible:ring-secondary-foreground disabled:opacity-30"
class="focus-visible:ring-secondary-foreground flex h-full w-8 cursor-pointer items-center justify-center rounded-r-lg border-none bg-transparent text-muted-foreground transition-colors hover:text-base-foreground focus-visible:ring-1 focus-visible:outline-none focus-visible:ring-inset disabled:opacity-30"
:disabled="disabled || modelValue >= max"
:aria-label="$t('g.increment')"
@click="handleStep(1)"

View File

@@ -60,7 +60,7 @@ onClickOutside(rootEl, () => {
cn(
'group relative flex flex-wrap items-center gap-2 rounded-lg bg-transparent p-2 text-xs text-base-foreground',
!internalDisabled &&
'hover:bg-modal-card-background-hovered focus-within:bg-modal-card-background-hovered',
'focus-within:bg-modal-card-background-hovered hover:bg-modal-card-background-hovered',
!disabled && !isEditing && 'cursor-pointer',
className
)
@@ -71,7 +71,7 @@ onClickOutside(rootEl, () => {
<i
v-if="!disabled && !isEditing"
aria-hidden="true"
class="icon-[lucide--square-pen] absolute bottom-2 right-2 size-4 text-muted-foreground"
class="absolute right-2 bottom-2 icon-[lucide--square-pen] size-4 text-muted-foreground"
/>
</TagsInputRoot>
</template>

View File

@@ -39,7 +39,7 @@ onUnmounted(() => {
v-bind="forwardedProps"
:class="
cn(
'min-h-6 flex-1 bg-transparent text-xs text-muted-foreground placeholder:text-muted-foreground focus:outline-none appearance-none border-none',
'min-h-6 flex-1 appearance-none border-none bg-transparent text-xs text-muted-foreground placeholder:text-muted-foreground focus:outline-none',
!isEditing && 'pointer-events-none',
className
)

View File

@@ -17,7 +17,7 @@ const forwardedProps = useForwardProps(restProps)
v-bind="forwardedProps"
:class="
cn(
'flex h-6 items-center gap-1 rounded-sm bg-modal-card-tag-background py-1 pl-2 pr-1 text-modal-card-tag-foreground backdrop-blur-sm ring-offset-base-background data-[state=active]:ring-2 data-[state=active]:ring-base-foreground data-[state=active]:ring-offset-1',
'flex h-6 items-center gap-1 rounded-sm bg-modal-card-tag-background py-1 pr-1 pl-2 text-modal-card-tag-foreground ring-offset-base-background backdrop-blur-sm data-[state=active]:ring-2 data-[state=active]:ring-base-foreground data-[state=active]:ring-offset-1',
className
)
"

View File

@@ -24,7 +24,7 @@ const { t } = useI18n()
:aria-label="t('g.removeTag')"
:class="
cn(
'opacity-60 hover:bg-transparent hover:opacity-100 transition-[opacity,width] duration-150 w-4 data-[disabled]:w-0 data-[disabled]:opacity-0 data-[disabled]:pointer-events-none overflow-hidden',
'w-4 overflow-hidden opacity-60 transition-[opacity,width] duration-150 hover:bg-transparent hover:opacity-100 data-[disabled]:pointer-events-none data-[disabled]:w-0 data-[disabled]:opacity-0',
className
)
"

View File

@@ -1,11 +1,11 @@
<template>
<div class="base-widget-layout rounded-2xl overflow-hidden relative">
<div class="base-widget-layout relative overflow-hidden rounded-2xl">
<Button
v-show="!isRightPanelOpen && hasRightPanel"
size="lg"
:class="
cn('absolute top-4 right-18 z-10', 'transition-opacity duration-200', {
'opacity-0 pointer-events-none': isRightPanelOpen || !hasRightPanel
'pointer-events-none opacity-0': isRightPanelOpen || !hasRightPanel
})
"
@click="toggleRightPanel"
@@ -14,7 +14,7 @@
</Button>
<Button
size="lg"
class="absolute top-4 right-6 z-10 transition-opacity duration-200 w-10"
class="absolute top-4 right-6 z-10 w-10 transition-opacity duration-200"
@click="closeDialog"
>
<i class="pi pi-times" />
@@ -29,18 +29,22 @@
PANEL_SIZES.maxWidth
]"
>
<slot name="leftPanel"></slot>
<slot name="leftPanel" />
</nav>
</Transition>
<div class="flex-1 flex bg-base-background">
<div class="flex flex-1 bg-base-background">
<div class="flex h-full w-full flex-col">
<header
v-if="$slots.header"
class="w-full h-18 px-6 flex items-center justify-between gap-2"
class="flex h-18 w-full items-center justify-between gap-2 px-6"
>
<div class="flex flex-1 shrink-0 gap-2">
<Button v-if="!notMobile" size="icon" @click="toggleLeftPanel">
<Button
v-if="!notMobile"
size="icon"
@click="toggleLeftPanel"
>
<i
:class="
cn(
@@ -51,13 +55,13 @@
"
/>
</Button>
<slot name="header"></slot>
<slot name="header" />
</div>
<slot name="header-right-area"></slot>
<slot name="header-right-area" />
<div
:class="
cn(
'flex justify-end gap-2 w-0',
'flex w-0 justify-end gap-2',
hasRightPanel && !isRightPanelOpen ? 'min-w-22' : 'min-w-10'
)
"
@@ -74,7 +78,7 @@
<main class="flex min-h-0 flex-1 flex-col">
<!-- Fallback title bar when no leftPanel is provided -->
<slot name="contentFilter"></slot>
<slot name="contentFilter" />
<h2
v-if="!$slots.leftPanel"
class="text-xxl m-0 px-6 pt-2 pb-6 capitalize"
@@ -82,17 +86,17 @@
{{ contentTitle }}
</h2>
<div
class="min-h-0 flex-1 px-6 pt-0 pb-10 overflow-y-auto scrollbar-custom"
class="scrollbar-custom min-h-0 flex-1 overflow-y-auto px-6 pt-0 pb-10"
>
<slot name="content"></slot>
<slot name="content" />
</div>
</main>
</div>
<aside
v-if="hasRightPanel && isRightPanelOpen"
class="w-1/4 min-w-40 max-w-80 pt-16 pb-8"
class="w-1/4 max-w-80 min-w-40 pt-16 pb-8"
>
<slot name="rightPanel"></slot>
<slot name="rightPanel" />
</aside>
</div>
</div>

View File

@@ -1,5 +1,8 @@
<template>
<i :class="icon" class="text-neutral text-sm shrink-0" />
<i
:class="icon"
class="text-neutral shrink-0 text-sm"
/>
</template>
<script setup lang="ts">

View File

@@ -5,7 +5,7 @@
disabled: !isOverflowing,
pt: { text: { class: 'whitespace-nowrap' } }
}"
class="flex cursor-pointer items-start gap-2 rounded-md px-4 py-3 text-sm transition-colors text-base-foreground"
class="flex cursor-pointer items-start gap-2 rounded-md px-4 py-3 text-sm text-base-foreground transition-colors"
:class="
active
? 'bg-interface-menu-component-surface-selected'
@@ -15,12 +15,21 @@
@mouseenter="checkOverflow"
@click="onClick"
>
<div v-if="icon" class="pt-0.5">
<div
v-if="icon"
class="pt-0.5"
>
<NavIcon :icon="icon" />
</div>
<i v-else class="text-neutral icon-[lucide--folder] text-xs shrink-0" />
<span ref="textRef" class="min-w-0 truncate">
<slot></slot>
<i
v-else
class="text-neutral icon-[lucide--folder] shrink-0 text-xs"
/>
<span
ref="textRef"
class="min-w-0 truncate"
>
<slot />
</span>
</div>
</template>

View File

@@ -2,7 +2,7 @@
<div
:class="
cn(
'flex items-center justify-between m-0 px-3 py-0 pt-5',
'm-0 flex items-center justify-between px-3 py-0 pt-5',
collapsible && 'cursor-pointer select-none'
)
"
@@ -15,7 +15,7 @@
v-if="collapsible"
:class="
cn(
'pi transition-transform duration-200 text-xs text-text-secondary ',
'pi text-xs text-text-secondary transition-transform duration-200',
isCollapsed ? 'pi-chevron-right' : 'pi-chevron-down'
)
"

View File

@@ -1,11 +1,11 @@
<template>
<div class="absolute left-2 bottom-2 flex flex-wrap justify-start gap-1">
<div class="absolute bottom-2 left-2 flex flex-wrap justify-start gap-1">
<span
v-for="badge in badges"
:key="badge.label"
:class="
cn(
'px-2 py-1 rounded text-xs font-bold uppercase tracking-wider text-modal-card-tag-foreground bg-modal-card-tag-background break-all'
'rounded bg-modal-card-tag-background px-2 py-1 text-xs font-bold tracking-wider break-all text-modal-card-tag-foreground uppercase'
)
"
>

View File

@@ -7,9 +7,9 @@
:tabindex="interactive ? 0 : -1"
:class="
cn(
'rounded-2xl overflow-hidden transition-all duration-200 bg-modal-card-background p-2 gap-2 flex flex-col h-full',
'flex h-full flex-col gap-2 overflow-hidden rounded-2xl bg-modal-card-background p-2 transition-all duration-200',
interactive &&
'group appearance-none bg-transparent m-0 outline-none text-left hover:bg-secondary-background focus:bg-secondary-background border-none focus:outline-solid outline-base-foreground outline-4'
'group m-0 appearance-none border-none bg-transparent text-left outline-4 outline-base-foreground outline-none hover:bg-secondary-background focus:bg-secondary-background focus:outline-solid'
)
"
@keydown.enter.self="interactive && $emit('select', asset)"
@@ -25,22 +25,25 @@
v-else
:src="asset.preview_url"
:alt="displayName"
class="size-full object-cover cursor-pointer"
class="size-full cursor-pointer object-cover"
role="button"
@click.self="interactive && $emit('select', asset)"
/>
>
<AssetBadgeGroup :badges="asset.badges" />
<IconGroup
v-if="showAssetOptions"
:class="
cn(
'absolute top-2 right-2 invisible group-hover:visible',
'invisible absolute top-2 right-2 group-hover:visible',
dropdownMenuButton?.isOpen && 'visible'
)
"
>
<MoreButton ref="dropdown-menu-button" size="sm">
<MoreButton
ref="dropdown-menu-button"
size="sm"
>
<template #default>
<Button
v-if="flags.assetRenameEnabled"
@@ -66,13 +69,13 @@
</MoreButton>
</IconGroup>
</div>
<div class="max-h-32 flex flex-col gap-2 justify-between flex-auto">
<div class="flex max-h-32 flex-auto flex-col justify-between gap-2">
<h3
:id="titleId"
v-tooltip.top="{ value: displayName, showDelay: tooltipDelay }"
:class="
cn(
'mb-2 m-0 text-base font-semibold line-clamp-2 wrap-anywhere',
'm-0 mb-2 line-clamp-2 text-base font-semibold wrap-anywhere',
'text-base-foreground'
)
"
@@ -90,22 +93,31 @@
v-tooltip.top="{ value: asset.description, showDelay: tooltipDelay }"
:class="
cn(
'm-0 text-sm leading-6 overflow-hidden [-webkit-box-orient:vertical] [-webkit-line-clamp:2] [display:-webkit-box] text-muted-foreground'
'm-0 [display:-webkit-box] overflow-hidden text-sm leading-6 text-muted-foreground [-webkit-box-orient:vertical] [-webkit-line-clamp:2]'
)
"
>
{{ asset.description }}
</p>
<div class="flex gap-4 text-xs text-muted-foreground mt-auto">
<span v-if="asset.stats.stars" class="flex items-center gap-1">
<div class="mt-auto flex gap-4 text-xs text-muted-foreground">
<span
v-if="asset.stats.stars"
class="flex items-center gap-1"
>
<i class="icon-[lucide--star] size-3" />
{{ asset.stats.stars }}
</span>
<span v-if="asset.stats.downloadCount" class="flex items-center gap-1">
<span
v-if="asset.stats.downloadCount"
class="flex items-center gap-1"
>
<i class="icon-[lucide--download] size-3" />
{{ asset.stats.downloadCount }}
</span>
<span v-if="asset.stats.formattedDate" class="flex items-center gap-1">
<span
v-if="asset.stats.formattedDate"
class="flex items-center gap-1"
>
<i class="icon-[lucide--clock] size-3" />
{{ asset.stats.formattedDate }}
</span>
@@ -192,7 +204,7 @@ function confirmDeletion() {
confirmText: t('g.delete'),
// TODO: These need to be put into the new Button Variants once we have them.
confirmClass: cn(
'bg-danger-200 text-base-foreground hover:bg-danger-200/80 focus:bg-danger-200/80 focus:ring ring-base-foreground'
'bg-danger-200 text-base-foreground ring-base-foreground hover:bg-danger-200/80 focus:bg-danger-200/80 focus:ring'
),
optionsDisabled,
onCancel: () => {

View File

@@ -1,10 +1,10 @@
<template>
<div
class="flex gap-4 items-center justify-between px-6 pt-2 pb-6"
class="flex items-center justify-between gap-4 px-6 pt-2 pb-6"
data-component-id="asset-filter-bar"
>
<div
class="flex gap-4 items-center"
class="flex items-center gap-4"
data-component-id="asset-filter-bar-left"
>
<MultiSelect
@@ -38,7 +38,10 @@
/>
</div>
<div class="flex items-center" data-component-id="asset-filter-bar-right">
<div
class="flex items-center"
data-component-id="asset-filter-bar-right"
>
<SingleSelect
v-model="sortBy"
:label="$t('assetBrowser.sortBy')"

View File

@@ -13,10 +13,10 @@
:tabindex="loading ? -1 : 0"
:class="
cn(
'flex flex-col overflow-hidden cursor-pointer p-2 transition-colors duration-200 rounded-lg',
'gap-2 select-none group',
'flex cursor-pointer flex-col overflow-hidden rounded-lg p-2 transition-colors duration-200',
'group gap-2 select-none',
selected
? 'ring-3 ring-inset ring-modal-card-border-highlighted'
? 'ring-3 ring-modal-card-border-highlighted ring-inset'
: 'hover:bg-modal-card-background-hovered/20'
)
"
@@ -79,7 +79,10 @@
<!-- Bottom Area: Media Info -->
<div class="flex-1">
<!-- Loading State -->
<div v-if="loading" class="flex justify-between items-start">
<div
v-if="loading"
class="flex items-start justify-between"
>
<div class="flex flex-col gap-1">
<div
class="h-4 w-24 animate-pulse rounded bg-modal-card-background"
@@ -94,7 +97,7 @@
<!-- Content -->
<div
v-else-if="asset && adaptedAsset"
class="flex justify-between items-end gap-1.5"
class="flex items-end justify-between gap-1.5"
>
<!-- Left side: Media name and metadata -->
<div class="flex flex-col gap-1">
@@ -108,7 +111,10 @@
</div>
<!-- Right side: Output count -->
<div v-if="showOutputCount" class="flex-shrink-0">
<div
v-if="showOutputCount"
class="flex-shrink-0"
>
<Button
v-tooltip.top.pt:pointer-events-none="
$t('mediaAsset.actions.seeMoreOutputs')

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