[Refactor] Manage comfyui-body elements with Vue (#2522)

Co-authored-by: github-actions <github-actions@github.com>
This commit is contained in:
Chenlei Hu
2025-02-11 18:37:08 -05:00
committed by GitHub
parent 8cfe814daa
commit 9017513979
9 changed files with 169 additions and 157 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 88 KiB

After

Width:  |  Height:  |  Size: 87 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 85 KiB

After

Width:  |  Height:  |  Size: 85 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 102 KiB

After

Width:  |  Height:  |  Size: 102 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 100 KiB

After

Width:  |  Height:  |  Size: 100 KiB

View File

@@ -45,8 +45,6 @@ body {
height: 100vh;
margin: 0;
overflow: hidden;
grid-template-columns: auto 1fr auto;
grid-template-rows: auto 1fr auto;
background: var(--bg-color) var(--bg-img);
color: var(--fg-color);
min-height: -webkit-fill-available;
@@ -56,87 +54,6 @@ body {
font-family: Arial, sans-serif;
}
/**
+------------------+------------------+------------------+
| |
| .comfyui-body- |
| top |
| (spans all cols) |
| |
+------------------+------------------+------------------+
| | | |
| .comfyui-body- | #graph-canvas | .comfyui-body- |
| left | | right |
| | | |
| | | |
+------------------+------------------+------------------+
| |
| .comfyui-body- |
| bottom |
| (spans all cols) |
| |
+------------------+------------------+------------------+
*/
.comfyui-body-top {
order: -5;
/* Span across all columns */
grid-column: 1/-1;
/* Position at the first row */
grid-row: 1;
/* Top menu bar dropdown needs to be above of graph canvas splitter overlay which is z-index: 999 */
/* Top menu bar z-index needs to be higher than bottom menu bar z-index as by default
pysssss's image feed is located at body-bottom, and it can overlap with the queue button, which
is located in body-top. */
z-index: 1001;
display: flex;
flex-direction: column;
}
.comfyui-body-left {
order: -4;
/* Position in the first column */
grid-column: 1;
/* Position below the top element */
grid-row: 2;
z-index: 10;
display: flex;
}
.graph-canvas-container {
width: 100%;
height: 100%;
order: -3;
grid-column: 2;
grid-row: 2;
position: relative;
overflow: hidden;
}
#graph-canvas {
width: 100%;
height: 100%;
touch-action: none;
}
.comfyui-body-right {
order: -2;
z-index: 10;
grid-column: 3;
grid-row: 2;
}
.comfyui-body-bottom {
order: 4;
/* Span across all columns */
grid-column: 1/-1;
grid-row: 3;
/* Bottom menu bar dropdown needs to be above of graph canvas splitter overlay which is z-index: 999 */
z-index: 1000;
display: flex;
flex-direction: column;
}
.comfy-multiline-input {
background-color: var(--comfy-input-bg);
color: var(--input-text);
@@ -753,7 +670,6 @@ audio.comfy-audio.empty-audio-widget {
left: 0;
width: 100%;
height: 100%;
pointer-events: none;
}
/* Set auto complete panel's width as it is not accessible within vue-root */

View File

@@ -1,28 +1,31 @@
<template>
<teleport to=".graph-canvas-container">
<!-- Load splitter overlay only after comfyApp is ready. -->
<!-- If load immediately, the top-level splitter stateKey won't be correctly
synced with the stateStorage (localStorage). -->
<LiteGraphCanvasSplitterOverlay
v-if="comfyAppReady && betaMenuEnabled && !workspaceStore.focusMode"
>
<template #side-bar-panel>
<SideToolbar />
</template>
<template #bottom-panel>
<BottomPanel />
</template>
<template #graph-canvas-panel>
<SecondRowWorkflowTabs
v-if="workflowTabsPosition === 'Topbar (2nd-row)'"
/>
<GraphCanvasMenu v-if="canvasMenuEnabled" />
</template>
</LiteGraphCanvasSplitterOverlay>
<TitleEditor />
<GraphCanvasMenu v-if="!betaMenuEnabled && canvasMenuEnabled" />
<canvas ref="canvasRef" id="graph-canvas" tabindex="1" />
</teleport>
<!-- Load splitter overlay only after comfyApp is ready. -->
<!-- If load immediately, the top-level splitter stateKey won't be correctly
synced with the stateStorage (localStorage). -->
<LiteGraphCanvasSplitterOverlay
v-if="comfyAppReady && betaMenuEnabled && !workspaceStore.focusMode"
>
<template #side-bar-panel>
<SideToolbar />
</template>
<template #bottom-panel>
<BottomPanel />
</template>
<template #graph-canvas-panel>
<SecondRowWorkflowTabs
v-if="workflowTabsPosition === 'Topbar (2nd-row)'"
/>
<GraphCanvasMenu v-if="canvasMenuEnabled" />
</template>
</LiteGraphCanvasSplitterOverlay>
<TitleEditor />
<GraphCanvasMenu v-if="!betaMenuEnabled && canvasMenuEnabled" />
<canvas
ref="canvasRef"
id="graph-canvas"
tabindex="1"
class="w-full h-full touch-none"
/>
<NodeSearchboxPopover />
<NodeTooltip v-if="tooltipEnabled" />
<NodeBadge />

View File

@@ -1,35 +1,33 @@
<template>
<teleport :to="teleportTarget">
<div
ref="topMenuRef"
class="comfyui-menu flex items-center"
v-show="showTopMenu"
:class="{ dropzone: isDropZone, 'dropzone-active': isDroppable }"
>
<h1 class="comfyui-logo mx-2 app-drag">ComfyUI</h1>
<CommandMenubar />
<div class="flex-grow min-w-0 app-drag h-full">
<WorkflowTabs v-if="workflowTabsPosition === 'Topbar'" />
</div>
<div class="comfyui-menu-right flex-shrink-0" ref="menuRight"></div>
<Actionbar />
<BottomPanelToggleButton class="flex-shrink-0" />
<Button
class="flex-shrink-0"
icon="pi pi-bars"
severity="secondary"
text
v-tooltip="{ value: $t('menu.hideMenu'), showDelay: 300 }"
:aria-label="$t('menu.hideMenu')"
@click="workspaceState.focusMode = true"
@contextmenu="showNativeMenu"
/>
<div
v-show="menuSetting !== 'Bottom'"
class="window-actions-spacer flex-shrink-0"
/>
<div
ref="topMenuRef"
class="comfyui-menu flex items-center"
v-show="showTopMenu"
:class="{ dropzone: isDropZone, 'dropzone-active': isDroppable }"
>
<h1 class="comfyui-logo mx-2 app-drag">ComfyUI</h1>
<CommandMenubar />
<div class="flex-grow min-w-0 app-drag h-full">
<WorkflowTabs v-if="workflowTabsPosition === 'Topbar'" />
</div>
</teleport>
<div class="comfyui-menu-right flex-shrink-0" ref="menuRight"></div>
<Actionbar />
<BottomPanelToggleButton class="flex-shrink-0" />
<Button
class="flex-shrink-0"
icon="pi pi-bars"
severity="secondary"
text
v-tooltip="{ value: $t('menu.hideMenu'), showDelay: 300 }"
:aria-label="$t('menu.hideMenu')"
@click="workspaceState.focusMode = true"
@contextmenu="showNativeMenu"
/>
<div
v-show="menuSetting !== 'Bottom'"
class="window-actions-spacer flex-shrink-0"
/>
</div>
<!-- Virtual top menu for native window (drag handle) -->
<div
@@ -64,11 +62,6 @@ const workflowTabsPosition = computed(() =>
)
const menuSetting = computed(() => settingStore.get('Comfy.UseNewMenu'))
const betaMenuEnabled = computed(() => menuSetting.value !== 'Disabled')
const teleportTarget = computed(() =>
settingStore.get('Comfy.UseNewMenu') === 'Top'
? '.comfyui-body-top'
: '.comfyui-body-bottom'
)
const showTopMenu = computed(
() => betaMenuEnabled.value && !workspaceState.focusMode
)

View File

@@ -203,13 +203,13 @@ export class ComfyApp {
this.vueAppReady = false
this.ui = new ComfyUI(this)
this.api = api
this.bodyTop = $el('div.comfyui-body-top', { parent: document.body })
this.bodyLeft = $el('div.comfyui-body-left', { parent: document.body })
this.bodyRight = $el('div.comfyui-body-right', { parent: document.body })
this.bodyBottom = $el('div.comfyui-body-bottom', { parent: document.body })
this.canvasContainer = $el('div.graph-canvas-container', {
parent: document.body
})
// Dummy placeholder elements before GraphCanvas is mounted.
this.bodyTop = $el('div.comfyui-body-top')
this.bodyLeft = $el('div.comfyui-body-left')
this.bodyRight = $el('div.comfyui-body-right')
this.bodyBottom = $el('div.comfyui-body-bottom')
this.canvasContainer = $el('div.graph-canvas-container')
this.menu = new ComfyAppMenu(this)
this.bypassBgColor = '#FF00FF'
@@ -774,6 +774,12 @@ export class ComfyApp {
* Set up the app on the page
*/
async setup(canvasEl: HTMLCanvasElement) {
this.bodyTop = document.getElementById('comfyui-body-top')
this.bodyLeft = document.getElementById('comfyui-body-left')
this.bodyRight = document.getElementById('comfyui-body-right')
this.bodyBottom = document.getElementById('comfyui-body-bottom')
this.canvasContainer = document.getElementById('graph-canvas-container')
this.canvasEl = canvasEl
this.resizeCanvas()

View File

@@ -1,8 +1,18 @@
<template>
<!-- Top menu bar needs to load before the GraphCanvas as it needs to host
the menu buttons added by legacy extension scripts.-->
<TopMenubar />
<GraphCanvas @ready="onGraphReady" />
<div class="comfyui-body grid h-screen w-screen overflow-hidden">
<div class="comfyui-body-top" id="comfyui-body-top">
<TopMenubar v-if="useNewMenu === 'Top'" />
</div>
<div class="comfyui-body-bottom" id="comfyui-body-bottom">
<TopMenubar v-if="useNewMenu === 'Bottom'" />
</div>
<div class="comfyui-body-left" id="comfyui-body-left" />
<div class="comfyui-body-right" id="comfyui-body-right" />
<div class="graph-canvas-container" id="graph-canvas-container">
<GraphCanvas @ready="onGraphReady" />
</div>
</div>
<GlobalToast />
<UnloadWindowConfirmDialog v-if="!isElectron()" />
<BrowserTabTitle />
@@ -13,7 +23,7 @@
import { useEventListener } from '@vueuse/core'
import type { ToastMessageOptions } from 'primevue/toast'
import { useToast } from 'primevue/usetoast'
import { onBeforeUnmount, onMounted, watch, watchEffect } from 'vue'
import { computed, onBeforeUnmount, onMounted, watch, watchEffect } from 'vue'
import { useI18n } from 'vue-i18n'
import BrowserTabTitle from '@/components/BrowserTabTitle.vue'
@@ -126,9 +136,11 @@ watchEffect(() => {
}
})
const useNewMenu = computed(() => {
return settingStore.get('Comfy.UseNewMenu')
})
watchEffect(() => {
const useNewMenu = settingStore.get('Comfy.UseNewMenu')
if (useNewMenu === 'Disabled') {
if (useNewMenu.value === 'Disabled') {
app.ui.menuContainer.style.setProperty('display', 'block')
app.ui.restoreMenuPosition()
} else {
@@ -226,3 +238,85 @@ const onGraphReady = () => {
)
}
</script>
<style scoped>
.comfyui-body {
grid-template-columns: auto 1fr auto;
grid-template-rows: auto 1fr auto;
}
/**
+------------------+------------------+------------------+
| |
| .comfyui-body- |
| top |
| (spans all cols) |
| |
+------------------+------------------+------------------+
| | | |
| .comfyui-body- | #graph-canvas | .comfyui-body- |
| left | | right |
| | | |
| | | |
+------------------+------------------+------------------+
| |
| .comfyui-body- |
| bottom |
| (spans all cols) |
| |
+------------------+------------------+------------------+
*/
.comfyui-body-top {
order: -5;
/* Span across all columns */
grid-column: 1/-1;
/* Position at the first row */
grid-row: 1;
/* Top menu bar dropdown needs to be above of graph canvas splitter overlay which is z-index: 999 */
/* Top menu bar z-index needs to be higher than bottom menu bar z-index as by default
pysssss's image feed is located at body-bottom, and it can overlap with the queue button, which
is located in body-top. */
z-index: 1001;
display: flex;
flex-direction: column;
}
.comfyui-body-left {
order: -4;
/* Position in the first column */
grid-column: 1;
/* Position below the top element */
grid-row: 2;
z-index: 10;
display: flex;
}
.graph-canvas-container {
width: 100%;
height: 100%;
order: -3;
grid-column: 2;
grid-row: 2;
position: relative;
overflow: hidden;
}
.comfyui-body-right {
order: -2;
z-index: 10;
grid-column: 3;
grid-row: 2;
}
.comfyui-body-bottom {
order: 4;
/* Span across all columns */
grid-column: 1/-1;
grid-row: 3;
/* Bottom menu bar dropdown needs to be above of graph canvas splitter overlay which is z-index: 999 */
z-index: 1000;
display: flex;
flex-direction: column;
}
</style>