From 42fb8ff04b7e487e2c1344f783cf4629de67d484 Mon Sep 17 00:00:00 2001 From: orkhanart <88044120+orkhanart@users.noreply.github.com> Date: Sat, 29 Nov 2025 12:51:44 -0800 Subject: [PATCH] feat(sidebar): Unified sidebar panels with 1-column grid layout MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Create LibraryGridCard component for consistent card design - Refactor LibrarySidebar with multi-select checkbox filters - Create AssetsSidebar with same styling as LibrarySidebar - Create TemplatesSidebar with category filters - Add expand icon to all sidebar panels (Library, Assets, Templates) - Add thumbnails to mock data for workflows, models, nodepacks - Remove categorization in favor of filter dropdowns - Add Library Hub view to workspace with route 馃 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- ComfyUI_vibe/src/assets/css/main.css | 14 +- ComfyUI_vibe/src/components.d.ts | 11 + .../common/sidebar/LibraryGridCard.vue | 99 +++++ .../src/components/common/sidebar/index.ts | 1 + .../v1/sidebar/LibraryBrandKitSection.vue | 84 ++-- .../v1/sidebar/LibraryModelsSection.vue | 50 ++- .../v1/sidebar/LibraryNodesSection.vue | 46 +- .../v1/sidebar/LibraryWorkflowsSection.vue | 42 +- .../components/v1/sidebar/V1SidebarPanel.vue | 18 +- .../components/v2/canvas/AssetsSidebar.vue | 314 ++++++++++++++ .../components/v2/canvas/LibrarySidebar.vue | 375 ++++++++++------ .../components/v2/canvas/TemplatesSidebar.vue | 326 ++++++++++++++ .../components/v2/layout/WorkspaceSidebar.vue | 6 +- .../src/components/v2/nodes/FlowNode.vue | 43 +- .../components/v2/nodes/FlowNodeMinimized.vue | 41 +- .../src/components/v2/nodes/NodeHeader.vue | 70 ++- .../src/components/v2/nodes/NodeSlots.vue | 8 +- .../src/components/v2/nodes/NodeWidgets.vue | 94 ++-- .../src/components/v2/nodes/SlotDot.vue | 17 +- .../v2/nodes/widgets/WidgetColor.vue | 21 +- .../v2/nodes/widgets/WidgetNumber.vue | 36 +- .../v2/nodes/widgets/WidgetSelect.vue | 26 +- .../v2/nodes/widgets/WidgetSlider.vue | 50 +-- .../v2/nodes/widgets/WidgetText.vue | 33 +- .../v2/nodes/widgets/WidgetToggle.vue | 16 +- ComfyUI_vibe/src/data/sidebarMockData.ts | 14 + ComfyUI_vibe/src/main.ts | 21 +- ComfyUI_vibe/src/router.ts | 5 + .../src/views/v2/workspace/LibraryView.vue | 409 ++++++++++++++++++ 29 files changed, 1822 insertions(+), 468 deletions(-) create mode 100644 ComfyUI_vibe/src/components/common/sidebar/LibraryGridCard.vue create mode 100644 ComfyUI_vibe/src/components/v2/canvas/AssetsSidebar.vue create mode 100644 ComfyUI_vibe/src/components/v2/canvas/TemplatesSidebar.vue create mode 100644 ComfyUI_vibe/src/views/v2/workspace/LibraryView.vue diff --git a/ComfyUI_vibe/src/assets/css/main.css b/ComfyUI_vibe/src/assets/css/main.css index 848f19f91..37a965ff6 100644 --- a/ComfyUI_vibe/src/assets/css/main.css +++ b/ComfyUI_vibe/src/assets/css/main.css @@ -313,6 +313,10 @@ body { .p-tooltip { --p-tooltip-padding: 0.25rem 0.5rem; --p-tooltip-border-radius: 4px; + --p-tooltip-background: #000000; + --p-tooltip-color: #fafafa; + --p-tooltip-show-delay: 100ms; + --p-tooltip-hide-delay: 0ms; } .p-tooltip .p-tooltip-text { @@ -323,18 +327,14 @@ body { letter-spacing: 0.05em; padding: 0.25rem 0.5rem; white-space: nowrap; + border: 1px solid #52525b; + border-radius: 4px; } /* Dark mode tooltip - for canvas/editor */ .dark .p-tooltip, .dark-theme .p-tooltip { - --p-tooltip-background: #27272a; - --p-tooltip-color: #e4e4e7; -} - -/* Light mode tooltip - for workspace */ -.p-tooltip { - --p-tooltip-background: #18181b; + --p-tooltip-background: #000000; --p-tooltip-color: #fafafa; } diff --git a/ComfyUI_vibe/src/components.d.ts b/ComfyUI_vibe/src/components.d.ts index ef4d23d6d..15b016c17 100644 --- a/ComfyUI_vibe/src/components.d.ts +++ b/ComfyUI_vibe/src/components.d.ts @@ -7,6 +7,7 @@ export {} /* prettier-ignore */ declare module 'vue' { export interface GlobalComponents { + AssetsSidebar: typeof import('./components/v2/canvas/AssetsSidebar.vue')['default'] AssetsTab: typeof import('./components/v2/workspace/AssetsTab.vue')['default'] CanvasBottomBar: typeof import('./components/v2/canvas/CanvasBottomBar.vue')['default'] CanvasLeftSidebar: typeof import('./components/v2/canvas/CanvasLeftSidebar.vue')['default'] @@ -19,7 +20,10 @@ declare module 'vue' { CreateProjectDialog: typeof import('./components/v2/workspace/CreateProjectDialog.vue')['default'] FlowNode: typeof import('./components/v2/nodes/FlowNode.vue')['default'] FlowNodeMinimized: typeof import('./components/v2/nodes/FlowNodeMinimized.vue')['default'] + FlowNodeTerminal: typeof import('./components/v2/nodes/terminal/FlowNodeTerminal.vue')['default'] + GlassNode: typeof import('./components/experimental/nodes/GlassNode.vue')['default'] LibraryBrandKitSection: typeof import('./components/v1/sidebar/LibraryBrandKitSection.vue')['default'] + LibraryGridCard: typeof import('./components/common/sidebar/LibraryGridCard.vue')['default'] LibraryModelsSection: typeof import('./components/v1/sidebar/LibraryModelsSection.vue')['default'] LibraryNodesSection: typeof import('./components/v1/sidebar/LibraryNodesSection.vue')['default'] LibrarySidebar: typeof import('./components/v2/canvas/LibrarySidebar.vue')['default'] @@ -37,12 +41,17 @@ declare module 'vue' { LinearTopNavbar: typeof import('./components/linear/LinearTopNavbar.vue')['default'] LinearWorkflowSidebar: typeof import('./components/linear/LinearWorkflowSidebar.vue')['default'] LinearWorkspace: typeof import('./components/linear/LinearWorkspace.vue')['default'] + MinimalNode: typeof import('./components/experimental/nodes/MinimalNode.vue')['default'] ModelsTab: typeof import('./components/v2/workspace/ModelsTab.vue')['default'] NodeHeader: typeof import('./components/v2/nodes/NodeHeader.vue')['default'] + NodeHeaderTerminal: typeof import('./components/v2/nodes/terminal/NodeHeaderTerminal.vue')['default'] NodePropertiesPanel: typeof import('./components/v2/canvas/NodePropertiesPanel.vue')['default'] NodeSlots: typeof import('./components/v2/nodes/NodeSlots.vue')['default'] + NodeSlotsTerminal: typeof import('./components/v2/nodes/terminal/NodeSlotsTerminal.vue')['default'] NodeWidgets: typeof import('./components/v2/nodes/NodeWidgets.vue')['default'] + NodeWidgetsTerminal: typeof import('./components/v2/nodes/terminal/NodeWidgetsTerminal.vue')['default'] PackagesTab: typeof import('./components/v2/workspace/PackagesTab.vue')['default'] + PillNode: typeof import('./components/experimental/nodes/PillNode.vue')['default'] RouterLink: typeof import('vue-router')['RouterLink'] RouterView: typeof import('vue-router')['RouterView'] SidebarGridCard: typeof import('./components/common/sidebar/SidebarGridCard.vue')['default'] @@ -51,6 +60,8 @@ declare module 'vue' { SidebarTreeItem: typeof import('./components/common/sidebar/SidebarTreeItem.vue')['default'] SidebarViewToggle: typeof import('./components/common/sidebar/SidebarViewToggle.vue')['default'] SlotDot: typeof import('./components/v2/nodes/SlotDot.vue')['default'] + TemplatesSidebar: typeof import('./components/v2/canvas/TemplatesSidebar.vue')['default'] + TerminalNode: typeof import('./components/experimental/nodes/TerminalNode.vue')['default'] V1SidebarAssetsTab: typeof import('./components/v1/sidebar/V1SidebarAssetsTab.vue')['default'] V1SidebarIconBar: typeof import('./components/v1/sidebar/V1SidebarIconBar.vue')['default'] V1SidebarModelsTab: typeof import('./components/v1/sidebar/V1SidebarModelsTab.vue')['default'] diff --git a/ComfyUI_vibe/src/components/common/sidebar/LibraryGridCard.vue b/ComfyUI_vibe/src/components/common/sidebar/LibraryGridCard.vue new file mode 100644 index 000000000..90fa44da0 --- /dev/null +++ b/ComfyUI_vibe/src/components/common/sidebar/LibraryGridCard.vue @@ -0,0 +1,99 @@ + + + diff --git a/ComfyUI_vibe/src/components/common/sidebar/index.ts b/ComfyUI_vibe/src/components/common/sidebar/index.ts index 2a8ade635..8b24d5120 100644 --- a/ComfyUI_vibe/src/components/common/sidebar/index.ts +++ b/ComfyUI_vibe/src/components/common/sidebar/index.ts @@ -1,5 +1,6 @@ export { default as SidebarTreeCategory } from './SidebarTreeCategory.vue' export { default as SidebarTreeItem } from './SidebarTreeItem.vue' export { default as SidebarGridCard } from './SidebarGridCard.vue' +export { default as LibraryGridCard } from './LibraryGridCard.vue' export { default as SidebarViewToggle } from './SidebarViewToggle.vue' export { default as SidebarSearchBox } from './SidebarSearchBox.vue' diff --git a/ComfyUI_vibe/src/components/v1/sidebar/LibraryBrandKitSection.vue b/ComfyUI_vibe/src/components/v1/sidebar/LibraryBrandKitSection.vue index bac8edce4..467559b05 100644 --- a/ComfyUI_vibe/src/components/v1/sidebar/LibraryBrandKitSection.vue +++ b/ComfyUI_vibe/src/components/v1/sidebar/LibraryBrandKitSection.vue @@ -21,6 +21,16 @@ function getAssetIcon(type: BrandAsset['type']): string { default: return 'pi pi-file' } } + +function getAssetTypeLabel(type: BrandAsset['type']): string { + switch (type) { + case 'logo': return 'Logo' + case 'font': return 'Font' + case 'template': return 'Template' + case 'guideline': return 'Guide' + default: return type + } +} @@ -255,13 +254,13 @@ function getHandleTop(index: number): string { diff --git a/ComfyUI_vibe/src/components/v2/nodes/widgets/WidgetNumber.vue b/ComfyUI_vibe/src/components/v2/nodes/widgets/WidgetNumber.vue index 414873a21..42cbbb01e 100644 --- a/ComfyUI_vibe/src/components/v2/nodes/widgets/WidgetNumber.vue +++ b/ComfyUI_vibe/src/components/v2/nodes/widgets/WidgetNumber.vue @@ -105,41 +105,40 @@ function decrement(): void { display: flex; align-items: center; justify-content: center; - width: 24px; - height: 26px; - background: #3f3f46; - border: 1px solid #3f3f46; - color: #a1a1aa; + width: 26px; + height: 24px; + background: #2a2a2e; + border: none; + color: #71717a; cursor: pointer; transition: all 0.15s; } .number-btn:first-child { - border-radius: 6px 0 0 6px; + border-radius: 4px 0 0 4px; } .number-btn:last-child { - border-radius: 0 6px 6px 0; + border-radius: 0 4px 4px 0; } .number-btn:hover:not(:disabled) { - background: #52525b; - color: #fafafa; + background: #3f3f46; + color: #a1a1aa; } .number-btn:disabled { - opacity: 0.5; + opacity: 0.4; cursor: not-allowed; } .number-input { flex: 1; - background: #27272a; - border: 1px solid #3f3f46; - border-left: none; - border-right: none; - color: #fafafa; - padding: 4px 8px; + height: 24px; + background: #2a2a2e; + border: none; + color: #e4e4e7; + padding: 0 8px; font-size: 11px; text-align: center; outline: none; @@ -154,12 +153,11 @@ function decrement(): void { } .number-input:focus { - border-color: #3b82f6; - box-shadow: 0 0 0 2px rgba(59, 130, 246, 0.2); + background: #323238; } .number-input:disabled { - opacity: 0.5; + opacity: 0.4; cursor: not-allowed; } diff --git a/ComfyUI_vibe/src/components/v2/nodes/widgets/WidgetSelect.vue b/ComfyUI_vibe/src/components/v2/nodes/widgets/WidgetSelect.vue index cea534ce8..b7103683f 100644 --- a/ComfyUI_vibe/src/components/v2/nodes/widgets/WidgetSelect.vue +++ b/ComfyUI_vibe/src/components/v2/nodes/widgets/WidgetSelect.vue @@ -48,32 +48,36 @@ function handleChange(event: Event): void { .custom-select { width: 100%; - background: #27272a; - border: 1px solid #3f3f46; - border-radius: 6px; - color: #fafafa; - padding: 6px 28px 6px 10px; + height: 24px; + background: #2a2a2e; + border: none; + border-radius: 4px; + color: #e4e4e7; + padding: 0 24px 0 10px; font-size: 11px; outline: none; cursor: pointer; appearance: none; - background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24' fill='none' stroke='%23a1a1aa' stroke-width='2'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E"); + background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='10' viewBox='0 0 24 24' fill='none' stroke='%2371717a' stroke-width='2'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E"); background-repeat: no-repeat; background-position: right 8px center; } +.custom-select:hover { + background: #323238; +} + .custom-select:focus { - border-color: #3b82f6; - box-shadow: 0 0 0 2px rgba(59, 130, 246, 0.2); + background: #323238; } .custom-select:disabled { - opacity: 0.5; + opacity: 0.4; cursor: not-allowed; } .custom-select option { - background: #27272a; - color: #fafafa; + background: #2a2a2e; + color: #e4e4e7; } diff --git a/ComfyUI_vibe/src/components/v2/nodes/widgets/WidgetSlider.vue b/ComfyUI_vibe/src/components/v2/nodes/widgets/WidgetSlider.vue index 5dbcf5caa..5d4c05c0d 100644 --- a/ComfyUI_vibe/src/components/v2/nodes/widgets/WidgetSlider.vue +++ b/ComfyUI_vibe/src/components/v2/nodes/widgets/WidgetSlider.vue @@ -94,13 +94,13 @@ function handleNumberBlur(event: Event): void { .widget-slider { display: flex; align-items: center; - gap: 8px; - padding: 2px 0; + gap: 6px; + height: 24px; } .slider-container { flex: 1; - height: 20px; + height: 24px; display: flex; align-items: center; } @@ -109,7 +109,7 @@ function handleNumberBlur(event: Event): void { -webkit-appearance: none; appearance: none; width: 100%; - height: 4px; + height: 3px; background: linear-gradient( to right, #3b82f6 0%, @@ -117,30 +117,30 @@ function handleNumberBlur(event: Event): void { #3f3f46 var(--fill-percent), #3f3f46 100% ); - border-radius: 4px; + border-radius: 2px; outline: none; cursor: pointer; } .custom-slider:disabled { - opacity: 0.5; + opacity: 0.4; cursor: not-allowed; } .custom-slider::-webkit-slider-thumb { -webkit-appearance: none; appearance: none; - width: 14px; - height: 14px; - background: #fafafa; - border: 2px solid #3b82f6; + width: 12px; + height: 12px; + background: #e4e4e7; + border: none; border-radius: 50%; cursor: grab; transition: background-color 0.15s, transform 0.15s; } .custom-slider::-webkit-slider-thumb:hover { - background: #3b82f6; + background: #fafafa; transform: scale(1.1); } @@ -150,17 +150,17 @@ function handleNumberBlur(event: Event): void { } .custom-slider::-moz-range-thumb { - width: 14px; - height: 14px; - background: #fafafa; - border: 2px solid #3b82f6; + width: 12px; + height: 12px; + background: #e4e4e7; + border: none; border-radius: 50%; cursor: grab; transition: background-color 0.15s, transform 0.15s; } .custom-slider::-moz-range-thumb:hover { - background: #3b82f6; + background: #fafafa; transform: scale(1.1); } @@ -174,12 +174,13 @@ function handleNumberBlur(event: Event): void { } .number-input { - width: 56px; - background: #27272a; - border: 1px solid #3f3f46; - border-radius: 6px; - color: #fafafa; - padding: 4px 6px; + width: 50px; + height: 24px; + background: #2a2a2e; + border: none; + border-radius: 4px; + color: #e4e4e7; + padding: 0 6px; font-size: 11px; text-align: center; outline: none; @@ -193,12 +194,11 @@ function handleNumberBlur(event: Event): void { } .number-input:focus { - border-color: #3b82f6; - box-shadow: 0 0 0 2px rgba(59, 130, 246, 0.2); + background: #323238; } .number-input:disabled { - opacity: 0.5; + opacity: 0.4; cursor: not-allowed; } diff --git a/ComfyUI_vibe/src/components/v2/nodes/widgets/WidgetText.vue b/ComfyUI_vibe/src/components/v2/nodes/widgets/WidgetText.vue index c280c0c82..bd8d25651 100644 --- a/ComfyUI_vibe/src/components/v2/nodes/widgets/WidgetText.vue +++ b/ComfyUI_vibe/src/components/v2/nodes/widgets/WidgetText.vue @@ -53,33 +53,48 @@ function handleInput(event: Event): void { width: 100%; } -.custom-input, +.custom-input { + width: 100%; + height: 24px; + background: #2a2a2e; + border: none; + border-radius: 4px; + color: #e4e4e7; + padding: 0 10px; + font-size: 11px; + outline: none; +} + .custom-textarea { width: 100%; - background: #27272a; - border: 1px solid #3f3f46; - border-radius: 6px; - color: #fafafa; + background: #2a2a2e; + border: none; + border-radius: 4px; + color: #e4e4e7; padding: 6px 10px; font-size: 11px; outline: none; resize: none; } +.custom-input:hover, +.custom-textarea:hover { + background: #323238; +} + .custom-input:focus, .custom-textarea:focus { - border-color: #3b82f6; - box-shadow: 0 0 0 2px rgba(59, 130, 246, 0.2); + background: #323238; } .custom-input:disabled, .custom-textarea:disabled { - opacity: 0.5; + opacity: 0.4; cursor: not-allowed; } .custom-input::placeholder, .custom-textarea::placeholder { - color: #71717a; + color: #52525b; } diff --git a/ComfyUI_vibe/src/components/v2/nodes/widgets/WidgetToggle.vue b/ComfyUI_vibe/src/components/v2/nodes/widgets/WidgetToggle.vue index e43524bca..85b0e4a97 100644 --- a/ComfyUI_vibe/src/components/v2/nodes/widgets/WidgetToggle.vue +++ b/ComfyUI_vibe/src/components/v2/nodes/widgets/WidgetToggle.vue @@ -43,6 +43,7 @@ function toggle(): void { .widget-toggle { display: flex; align-items: center; + height: 24px; } .toggle-button { @@ -54,16 +55,16 @@ function toggle(): void { } .toggle-button:disabled { - opacity: 0.5; + opacity: 0.4; cursor: not-allowed; } .toggle-track { display: block; - width: 36px; - height: 20px; + width: 32px; + height: 16px; background: #3f3f46; - border-radius: 10px; + border-radius: 8px; position: relative; transition: background-color 0.2s; } @@ -76,12 +77,11 @@ function toggle(): void { position: absolute; top: 2px; left: 2px; - width: 16px; - height: 16px; - background: #fafafa; + width: 12px; + height: 12px; + background: #e4e4e7; border-radius: 50%; transition: transform 0.2s; - box-shadow: 0 1px 3px rgba(0, 0, 0, 0.3); } .toggle-button.active .toggle-thumb { diff --git a/ComfyUI_vibe/src/data/sidebarMockData.ts b/ComfyUI_vibe/src/data/sidebarMockData.ts index 5d87ef5c6..d25f14fb2 100644 --- a/ComfyUI_vibe/src/data/sidebarMockData.ts +++ b/ComfyUI_vibe/src/data/sidebarMockData.ts @@ -244,6 +244,7 @@ export interface SharedWorkflow { nodes: number category: string starred: boolean + thumbnail?: string } export interface TeamModel { @@ -254,6 +255,7 @@ export interface TeamModel { size: string author: TeamMember downloads: number + thumbnail?: string } export interface NodePack { @@ -264,6 +266,7 @@ export interface NodePack { nodes: number author: string installed: boolean + thumbnail?: string } export const TEMPLATE_CATEGORIES_DATA: TemplateCategory[] = [ @@ -354,6 +357,7 @@ export function createSharedWorkflowsData(members: TeamMember[]): SharedWorkflow nodes: 12, category: 'Production', starred: true, + thumbnail: '/assets/card_images/workflow_01.webp', }, { id: '2', @@ -364,6 +368,7 @@ export function createSharedWorkflowsData(members: TeamMember[]): SharedWorkflow nodes: 18, category: 'Marketing', starred: true, + thumbnail: '/assets/card_images/2690a78c-c210-4a52-8c37-3cb5bc4d9e71.webp', }, { id: '3', @@ -374,6 +379,7 @@ export function createSharedWorkflowsData(members: TeamMember[]): SharedWorkflow nodes: 24, category: 'Production', starred: false, + thumbnail: '/assets/card_images/bacb46ea-7e63-4f19-a253-daf41461e98f.webp', }, { id: '4', @@ -384,6 +390,7 @@ export function createSharedWorkflowsData(members: TeamMember[]): SharedWorkflow nodes: 8, category: 'Marketing', starred: false, + thumbnail: '/assets/card_images/228616f4-12ad-426d-84fb-f20e488ba7ee.webp', }, ] } @@ -398,6 +405,7 @@ export function createTeamModelsData(members: TeamMember[]): TeamModel[] { size: '144 MB', author: members[0]!, downloads: 156, + thumbnail: '/assets/card_images/683255d3-1d10-43d9-a6ff-ef142061e88a.webp', }, { id: '2', @@ -407,6 +415,7 @@ export function createTeamModelsData(members: TeamMember[]): TeamModel[] { size: '6.94 GB', author: members[1]!, downloads: 89, + thumbnail: '/assets/card_images/91f1f589-ddb4-4c4f-b3a7-ba30fc271987.webp', }, { id: '3', @@ -416,6 +425,7 @@ export function createTeamModelsData(members: TeamMember[]): TeamModel[] { size: '72 MB', author: members[2]!, downloads: 234, + thumbnail: '/assets/card_images/28e9f7ea-ef00-48e8-849d-8752a34939c7.webp', }, { id: '4', @@ -425,6 +435,7 @@ export function createTeamModelsData(members: TeamMember[]): TeamModel[] { size: '24 KB', author: members[0]!, downloads: 312, + thumbnail: '/assets/card_images/comfyui_workflow.jpg', }, ] } @@ -438,6 +449,7 @@ export const NODE_PACKS_DATA: NodePack[] = [ nodes: 8, author: 'Netflix Creative Tech', installed: true, + thumbnail: '/assets/card_images/can-you-rate-my-comfyui-workflow-v0-o9clchhji39c1.webp', }, { id: '2', @@ -447,6 +459,7 @@ export const NODE_PACKS_DATA: NodePack[] = [ nodes: 4, author: 'Netflix Creative Tech', installed: true, + thumbnail: '/assets/card_images/dda28581-37c8-44da-8822-57d1ccc2118c_2130x1658.png', }, { id: '3', @@ -456,5 +469,6 @@ export const NODE_PACKS_DATA: NodePack[] = [ nodes: 6, author: 'Netflix Creative Tech', installed: false, + thumbnail: '/assets/card_images/workflow_01.webp', }, ] diff --git a/ComfyUI_vibe/src/main.ts b/ComfyUI_vibe/src/main.ts index 1653ad217..966b485b5 100644 --- a/ComfyUI_vibe/src/main.ts +++ b/ComfyUI_vibe/src/main.ts @@ -84,7 +84,24 @@ app.use(PrimeVue, { app.use(ToastService) app.use(ConfirmationService) -// PrimeVue directives -app.directive('tooltip', Tooltip) +// PrimeVue directives with custom defaults +app.directive('tooltip', { + ...Tooltip, + getSSRProps() { + return {} + }, + mounted(el, binding) { + // Set fast show delay (100ms) as default + const value = binding.value + if (typeof value === 'string') { + binding.value = { value, showDelay: 100, hideDelay: 0 } + } else if (typeof value === 'object' && value !== null) { + binding.value = { showDelay: 100, hideDelay: 0, ...value } + } + Tooltip.mounted(el, binding) + }, + updated: Tooltip.updated, + unmounted: Tooltip.unmounted +}) app.mount('#app') diff --git a/ComfyUI_vibe/src/router.ts b/ComfyUI_vibe/src/router.ts index 024ddf213..49acdc4c2 100644 --- a/ComfyUI_vibe/src/router.ts +++ b/ComfyUI_vibe/src/router.ts @@ -59,6 +59,11 @@ const v2Routes: RouteRecordRaw[] = [ name: 'workspace-templates', component: () => import('./views/v2/workspace/TemplatesView.vue') }, + { + path: 'library', + name: 'workspace-library', + component: () => import('./views/v2/workspace/LibraryView.vue') + }, { path: 'trash', name: 'workspace-trash', diff --git a/ComfyUI_vibe/src/views/v2/workspace/LibraryView.vue b/ComfyUI_vibe/src/views/v2/workspace/LibraryView.vue new file mode 100644 index 000000000..3b265e017 --- /dev/null +++ b/ComfyUI_vibe/src/views/v2/workspace/LibraryView.vue @@ -0,0 +1,409 @@ + + +