diff --git a/browser_tests/fixtures/components/Topbar.ts b/browser_tests/fixtures/components/Topbar.ts index 81fcf67642..b138ff7b74 100644 --- a/browser_tests/fixtures/components/Topbar.ts +++ b/browser_tests/fixtures/components/Topbar.ts @@ -50,7 +50,7 @@ export class Topbar { workflowName: string, command: 'Save' | 'Save As' | 'Export' ) { - await this.triggerTopbarCommand(['Workflow', command]) + await this.triggerTopbarCommand(['File', command]) await this.getSaveDialog().fill(workflowName) await this.page.keyboard.press('Enter') @@ -72,8 +72,8 @@ export class Topbar { } async triggerTopbarCommand(path: string[]) { - if (path.length < 2) { - throw new Error('Path is too short') + if (path.length < 1) { + throw new Error('Path cannot be empty') } const menu = await this.openTopbarMenu() @@ -85,6 +85,13 @@ export class Topbar { .locator('.p-tieredmenu-item') .filter({ has: topLevelMenuItem }) await topLevelMenu.waitFor({ state: 'visible' }) + + // Handle top-level commands (like "New") + if (path.length === 1) { + await topLevelMenuItem.click() + return + } + await topLevelMenu.hover() let currentMenu = topLevelMenu diff --git a/browser_tests/tests/groupNode.spec.ts b/browser_tests/tests/groupNode.spec.ts index a6cb1e67f0..fb282e6a77 100644 --- a/browser_tests/tests/groupNode.spec.ts +++ b/browser_tests/tests/groupNode.spec.ts @@ -268,10 +268,7 @@ test.describe('Group Node', () => { await comfyPage.setSetting('Comfy.ConfirmClear', false) // Clear workflow - await comfyPage.menu.topbar.triggerTopbarCommand([ - 'Edit', - 'Clear Workflow' - ]) + await comfyPage.executeCommand('Comfy.ClearWorkflow') await comfyPage.ctrlV() await verifyNodeLoaded(comfyPage, 1) @@ -280,7 +277,7 @@ test.describe('Group Node', () => { test('Copies and pastes group node into a newly created blank workflow', async ({ comfyPage }) => { - await comfyPage.menu.topbar.triggerTopbarCommand(['Workflow', 'New']) + await comfyPage.menu.topbar.triggerTopbarCommand(['New']) await comfyPage.ctrlV() await verifyNodeLoaded(comfyPage, 1) }) @@ -296,7 +293,7 @@ test.describe('Group Node', () => { test('Serializes group node after copy and paste across workflows', async ({ comfyPage }) => { - await comfyPage.menu.topbar.triggerTopbarCommand(['Workflow', 'New']) + await comfyPage.menu.topbar.triggerTopbarCommand(['New']) await comfyPage.ctrlV() const currentGraphState = await comfyPage.page.evaluate(() => window['app'].graph.serialize() diff --git a/browser_tests/tests/interaction.spec.ts b/browser_tests/tests/interaction.spec.ts index a19248c2ea..9341077921 100644 --- a/browser_tests/tests/interaction.spec.ts +++ b/browser_tests/tests/interaction.spec.ts @@ -684,7 +684,7 @@ test.describe('Load workflow', () => { workflowA = generateUniqueFilename() await comfyPage.menu.topbar.saveWorkflow(workflowA) workflowB = generateUniqueFilename() - await comfyPage.menu.topbar.triggerTopbarCommand(['Workflow', 'New']) + await comfyPage.menu.topbar.triggerTopbarCommand(['New']) await comfyPage.menu.topbar.saveWorkflow(workflowB) // Wait for localStorage to persist the workflow paths before reloading diff --git a/browser_tests/tests/menu.spec.ts b/browser_tests/tests/menu.spec.ts index a771257f25..1eabe222c7 100644 --- a/browser_tests/tests/menu.spec.ts +++ b/browser_tests/tests/menu.spec.ts @@ -75,7 +75,7 @@ test.describe('Menu', () => { test('Displays keybinding next to item', async ({ comfyPage }) => { await comfyPage.menu.topbar.openTopbarMenu() - const workflowMenuItem = comfyPage.menu.topbar.getMenuItem('Workflow') + const workflowMenuItem = comfyPage.menu.topbar.getMenuItem('File') await workflowMenuItem.hover() const exportTag = comfyPage.page.locator('.keybinding-tag', { hasText: 'Ctrl + s' diff --git a/browser_tests/tests/rerouteNode.spec.ts b/browser_tests/tests/rerouteNode.spec.ts index 4c7065e3fb..b61014f6df 100644 --- a/browser_tests/tests/rerouteNode.spec.ts +++ b/browser_tests/tests/rerouteNode.spec.ts @@ -18,7 +18,7 @@ test.describe('Reroute Node', () => { [workflowName]: workflowName }) await comfyPage.setup() - await comfyPage.menu.topbar.triggerTopbarCommand(['Workflow', 'New']) + await comfyPage.menu.topbar.triggerTopbarCommand(['New']) // Insert the workflow const workflowsTab = comfyPage.menu.workflowsTab diff --git a/browser_tests/tests/workflowTabThumbnail.spec.ts b/browser_tests/tests/workflowTabThumbnail.spec.ts index a1869430b5..31b15067f6 100644 --- a/browser_tests/tests/workflowTabThumbnail.spec.ts +++ b/browser_tests/tests/workflowTabThumbnail.spec.ts @@ -63,7 +63,7 @@ test.describe('Workflow Tab Thumbnails', () => { test('Should show thumbnail when hovering over a non-active tab', async ({ comfyPage }) => { - await comfyPage.menu.topbar.triggerTopbarCommand(['Workflow', 'New']) + await comfyPage.menu.topbar.triggerTopbarCommand(['New']) const thumbnailImg = await getTabThumbnailImage( comfyPage, 0, @@ -73,7 +73,7 @@ test.describe('Workflow Tab Thumbnails', () => { }) test('Should not show thumbnail for active tab', async ({ comfyPage }) => { - await comfyPage.menu.topbar.triggerTopbarCommand(['Workflow', 'New']) + await comfyPage.menu.topbar.triggerTopbarCommand(['New']) const thumbnailImg = await getTabThumbnailImage( comfyPage, 1, @@ -105,7 +105,7 @@ test.describe('Workflow Tab Thumbnails', () => { await comfyPage.nextFrame() // Create a new workflow (tab 1) which will be empty - await comfyPage.menu.topbar.triggerTopbarCommand(['Workflow', 'New']) + await comfyPage.menu.topbar.triggerTopbarCommand(['New']) await comfyPage.nextFrame() // Now we have two tabs: tab 0 (default workflow with nodes) and tab 1 (empty) diff --git a/src/assets/icons/custom/ai-model.svg b/src/assets/icons/custom/ai-model.svg new file mode 100644 index 0000000000..ede8e5c7e8 --- /dev/null +++ b/src/assets/icons/custom/ai-model.svg @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/src/assets/icons/custom/node.svg b/src/assets/icons/custom/node.svg new file mode 100644 index 0000000000..3239b59bd7 --- /dev/null +++ b/src/assets/icons/custom/node.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/src/assets/icons/custom/template.svg b/src/assets/icons/custom/template.svg new file mode 100644 index 0000000000..2a2a75f8da --- /dev/null +++ b/src/assets/icons/custom/template.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/src/components/sidebar/SideToolbar.vue b/src/components/sidebar/SideToolbar.vue index 0ef8598d1c..72a451d81c 100644 --- a/src/components/sidebar/SideToolbar.vue +++ b/src/components/sidebar/SideToolbar.vue @@ -8,10 +8,13 @@ :icon-badge="tab.iconBadge" :tooltip="tab.tooltip" :tooltip-suffix="getTabTooltipSuffix(tab)" + :label="tab.label || tab.title" + :is-small="isSmall" :selected="tab.id === selectedTab?.id" :class="tab.id + '-tab-button'" @click="onTabClick(tab)" /> +
@@ -43,6 +46,7 @@ import type { SidebarTabExtension } from '@/types/extensionTypes' import SidebarHelpCenterIcon from './SidebarHelpCenterIcon.vue' import SidebarIcon from './SidebarIcon.vue' import SidebarLogoutIcon from './SidebarLogoutIcon.vue' +import SidebarTemplatesButton from './SidebarTemplatesButton.vue' const workspaceStore = useWorkspaceStore() const settingStore = useSettingStore() @@ -86,7 +90,7 @@ const getTabTooltipSuffix = (tab: SidebarTabExtension) => { box-shadow: var(--bar-shadow); --sidebar-width: 4rem; - --sidebar-icon-size: 1.5rem; + --sidebar-icon-size: 1rem; } .side-tool-bar-container.small-sidebar { diff --git a/src/components/sidebar/SidebarHelpCenterIcon.vue b/src/components/sidebar/SidebarHelpCenterIcon.vue index c37cd973e8..1a15b8487f 100644 --- a/src/components/sidebar/SidebarHelpCenterIcon.vue +++ b/src/components/sidebar/SidebarHelpCenterIcon.vue @@ -58,11 +58,12 @@ diff --git a/src/components/sidebar/tabs/NodeLibrarySidebarTab.vue b/src/components/sidebar/tabs/NodeLibrarySidebarTab.vue index c80e1cc2f2..533934eaa5 100644 --- a/src/components/sidebar/tabs/NodeLibrarySidebarTab.vue +++ b/src/components/sidebar/tabs/NodeLibrarySidebarTab.vue @@ -30,11 +30,18 @@ />