Skip to content

Commit 62f3ba0

Browse files
pythongosssssgithub-actions
andauthored
V3 UI - Tabs & Menu rework (#4374)
Co-authored-by: github-actions <[email protected]>
1 parent 2338cbd commit 62f3ba0

33 files changed

+1054
-228
lines changed

browser_tests/fixtures/ComfyPage.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -168,7 +168,7 @@ export class ComfyPage {
168168
this.menu = new ComfyMenu(page)
169169
this.actionbar = new ComfyActionbar(page)
170170
this.templates = new ComfyTemplates(page)
171-
this.settingDialog = new SettingDialog(page)
171+
this.settingDialog = new SettingDialog(page, this)
172172
this.confirmDialog = new ConfirmDialog(page)
173173
}
174174

browser_tests/fixtures/components/SettingDialog.ts

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,19 @@
11
import { Page } from '@playwright/test'
22

3+
import { ComfyPage } from '../ComfyPage'
4+
35
export class SettingDialog {
4-
constructor(public readonly page: Page) {}
6+
constructor(
7+
public readonly page: Page,
8+
public readonly comfyPage: ComfyPage
9+
) {}
510

611
get root() {
712
return this.page.locator('div.settings-container')
813
}
914

1015
async open() {
11-
const button = this.page.locator('button.comfy-settings-btn:visible')
12-
await button.click()
16+
await this.comfyPage.executeCommand('Comfy.ShowSettingsDialog')
1317
await this.page.waitForSelector('div.settings-container')
1418
}
1519

browser_tests/fixtures/components/Topbar.ts

Lines changed: 19 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,6 @@ export class Topbar {
1515
.innerText()
1616
}
1717

18-
async openSubmenuMobile() {
19-
await this.page.locator('.p-menubar-mobile .p-menubar-button').click()
20-
}
21-
2218
getMenuItem(itemLabel: string): Locator {
2319
return this.page.locator(`.p-menubar-item-label:text-is("${itemLabel}")`)
2420
}
@@ -68,31 +64,41 @@ export class Topbar {
6864
await this.getSaveDialog().waitFor({ state: 'hidden', timeout: 500 })
6965
}
7066

67+
async openTopbarMenu() {
68+
await this.page.locator('.comfyui-logo-wrapper').click()
69+
const menu = this.page.locator('.comfy-command-menu')
70+
await menu.waitFor({ state: 'visible' })
71+
return menu
72+
}
73+
7174
async triggerTopbarCommand(path: string[]) {
7275
if (path.length < 2) {
7376
throw new Error('Path is too short')
7477
}
7578

79+
const menu = await this.openTopbarMenu()
7680
const tabName = path[0]
77-
const topLevelMenu = this.page.locator(
78-
`.top-menubar .p-menubar-item-label:text-is("${tabName}")`
81+
const topLevelMenuItem = this.page.locator(
82+
`.p-menubar-item-label:text-is("${tabName}")`
7983
)
84+
const topLevelMenu = menu
85+
.locator('.p-tieredmenu-item')
86+
.filter({ has: topLevelMenuItem })
8087
await topLevelMenu.waitFor({ state: 'visible' })
81-
await topLevelMenu.click()
88+
await topLevelMenu.hover()
8289

90+
let currentMenu = topLevelMenu
8391
for (let i = 1; i < path.length; i++) {
8492
const commandName = path[i]
85-
const menuItem = this.page
93+
const menuItem = currentMenu
8694
.locator(
87-
`.top-menubar .p-menubar-submenu .p-menubar-item:has-text("${commandName}")`
95+
`.p-tieredmenu-submenu .p-tieredmenu-item:has-text("${commandName}")`
8896
)
8997
.first()
9098
await menuItem.waitFor({ state: 'visible' })
9199
await menuItem.hover()
92-
93-
if (i === path.length - 1) {
94-
await menuItem.click()
95-
}
100+
currentMenu = menuItem
96101
}
102+
await currentMenu.click()
97103
}
98104
}

browser_tests/tests/interaction.spec.ts

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -769,27 +769,37 @@ test.describe('Viewport settings', () => {
769769
}) => {
770770
// Screenshot the canvas element
771771
await comfyPage.menu.topbar.saveWorkflow('Workflow A')
772-
await expect(comfyPage.canvas).toHaveScreenshot('viewport-workflow-a.png')
772+
await comfyPage.nextFrame()
773+
const screenshotA = (await comfyPage.canvas.screenshot()).toString('base64')
773774

774775
// Save workflow as a new file, then zoom out before screen shot
775776
await comfyPage.menu.topbar.saveWorkflowAs('Workflow B')
776777
await comfyMouse.move(comfyPage.emptySpace)
777778
for (let i = 0; i < 4; i++) {
778779
await comfyMouse.wheel(0, 60)
779780
}
780-
await expect(comfyPage.canvas).toHaveScreenshot('viewport-workflow-b.png')
781+
782+
await comfyPage.nextFrame()
783+
const screenshotB = (await comfyPage.canvas.screenshot()).toString('base64')
784+
785+
// Ensure that the screenshots are different due to zoom level
786+
expect(screenshotB).not.toBe(screenshotA)
781787

782788
const tabA = comfyPage.menu.topbar.getWorkflowTab('Workflow A')
783789
const tabB = comfyPage.menu.topbar.getWorkflowTab('Workflow B')
784790

785791
// Go back to Workflow A
786792
await tabA.click()
787793
await comfyPage.nextFrame()
788-
await expect(comfyPage.canvas).toHaveScreenshot('viewport-workflow-a.png')
794+
expect((await comfyPage.canvas.screenshot()).toString('base64')).toBe(
795+
screenshotA
796+
)
789797

790798
// And back to Workflow B
791799
await tabB.click()
792800
await comfyPage.nextFrame()
793-
await expect(comfyPage.canvas).toHaveScreenshot('viewport-workflow-b.png')
801+
expect((await comfyPage.canvas.screenshot()).toString('base64')).toBe(
802+
screenshotB
803+
)
794804
})
795805
})
Binary file not shown.
Binary file not shown.

browser_tests/tests/menu.spec.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ test.describe('Menu', () => {
6363
test('@mobile Items fully visible on mobile screen width', async ({
6464
comfyPage
6565
}) => {
66-
await comfyPage.menu.topbar.openSubmenuMobile()
66+
await comfyPage.menu.topbar.openTopbarMenu()
6767
const topLevelMenuItem = comfyPage.page
6868
.locator('a.p-menubar-item-link')
6969
.first()
@@ -74,8 +74,9 @@ test.describe('Menu', () => {
7474
})
7575

7676
test('Displays keybinding next to item', async ({ comfyPage }) => {
77+
await comfyPage.menu.topbar.openTopbarMenu()
7778
const workflowMenuItem = comfyPage.menu.topbar.getMenuItem('Workflow')
78-
await workflowMenuItem.click()
79+
await workflowMenuItem.hover()
7980
const exportTag = comfyPage.page.locator('.keybinding-tag', {
8081
hasText: 'Ctrl + s'
8182
})

src/components/actionbar/ComfyActionbar.vue

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -30,10 +30,11 @@ import ComfyQueueButton from './ComfyQueueButton.vue'
3030
3131
const settingsStore = useSettingStore()
3232
33-
const visible = computed(
34-
() => settingsStore.get('Comfy.UseNewMenu') !== 'Disabled'
35-
)
33+
const position = computed(() => settingsStore.get('Comfy.UseNewMenu'))
34+
35+
const visible = computed(() => position.value !== 'Disabled')
3636
37+
const topMenuRef = inject<Ref<HTMLDivElement | null>>('topMenuRef')
3738
const panelRef = ref<HTMLElement | null>(null)
3839
const dragHandleRef = ref<HTMLElement | null>(null)
3940
const isDocked = useLocalStorage('Comfy.MenuPosition.Docked', false)
@@ -49,7 +50,16 @@ const {
4950
} = useDraggable(panelRef, {
5051
initialValue: { x: 0, y: 0 },
5152
handle: dragHandleRef,
52-
containerElement: document.body
53+
containerElement: document.body,
54+
onMove: (event) => {
55+
// Prevent dragging the menu over the top of the tabs
56+
if (position.value === 'Top') {
57+
const minY = topMenuRef?.value?.getBoundingClientRect().top ?? 40
58+
if (event.y < minY) {
59+
event.y = minY
60+
}
61+
}
62+
}
5363
})
5464
5565
// Update storedPosition when x or y changes
@@ -182,7 +192,6 @@ const adjustMenuPosition = () => {
182192
183193
useEventListener(window, 'resize', adjustMenuPosition)
184194
185-
const topMenuRef = inject<Ref<HTMLDivElement | null>>('topMenuRef')
186195
const topMenuBounds = useElementBounding(topMenuRef)
187196
const overlapThreshold = 20 // pixels
188197
const isOverlappingWithTopMenu = computed(() => {

0 commit comments

Comments
 (0)