mirror of
https://github.com/Comfy-Org/ComfyUI_frontend.git
synced 2026-03-05 21:20:12 +00:00
Make action bar draggable (#1035)
* Basic draggable * Nowrap * Prevent double reset * Persist position * nit * nit * Window resize adjustment * Fix playwright test
This commit is contained in:
@@ -640,9 +640,10 @@ export class ComfyPage {
|
||||
y: 645
|
||||
}
|
||||
})
|
||||
await page.locator('input[type="text"]').click()
|
||||
await page.locator('input[type="text"]').fill('128')
|
||||
await page.locator('input[type="text"]').press('Enter')
|
||||
const dialogInput = page.locator('.graphdialog input[type="text"]')
|
||||
await dialogInput.click()
|
||||
await dialogInput.fill('128')
|
||||
await dialogInput.press('Enter')
|
||||
await this.nextFrame()
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,13 @@
|
||||
<template>
|
||||
<Panel v-if="visible" class="app-menu">
|
||||
<div class="app-menu-content flex align-center">
|
||||
<Panel
|
||||
v-show="visible"
|
||||
class="app-menu w-fit"
|
||||
:style="style"
|
||||
:class="{ 'is-dragging': isDragging }"
|
||||
>
|
||||
<div class="app-menu-content flex items-center" ref="panelRef">
|
||||
<span class="drag-handle cursor-move mr-2 p-0!" ref="dragHandleRef">
|
||||
</span>
|
||||
<div class="queue-button-group flex">
|
||||
<SplitButton
|
||||
class="comfyui-queue-button"
|
||||
@@ -23,7 +30,7 @@
|
||||
</template>
|
||||
</SplitButton>
|
||||
<BatchCountEdit />
|
||||
<ButtonGroup class="execution-actions ml-2">
|
||||
<ButtonGroup class="execution-actions ml-2 flex flex-nowrap">
|
||||
<Button
|
||||
v-tooltip.bottom="$t('menu.interrupt')"
|
||||
icon="pi pi-times"
|
||||
@@ -44,7 +51,7 @@
|
||||
</ButtonGroup>
|
||||
</div>
|
||||
<Divider layout="vertical" class="mx-2" />
|
||||
<ButtonGroup>
|
||||
<ButtonGroup class="flex flex-nowrap">
|
||||
<Button
|
||||
v-tooltip.bottom="$t('menu.refresh')"
|
||||
icon="pi pi-refresh"
|
||||
@@ -66,7 +73,7 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { computed } from 'vue'
|
||||
import { computed, nextTick, onMounted, ref, watch } from 'vue'
|
||||
import Panel from 'primevue/panel'
|
||||
import Divider from 'primevue/divider'
|
||||
import SplitButton from 'primevue/splitbutton'
|
||||
@@ -84,6 +91,8 @@ import { useSettingStore } from '@/stores/settingStore'
|
||||
import { useCommandStore } from '@/stores/commandStore'
|
||||
import { MenuItem } from 'primevue/menuitem'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
import { useDraggable, useEventListener, useLocalStorage } from '@vueuse/core'
|
||||
import { debounce, clamp } from 'lodash'
|
||||
|
||||
const settingsStore = useSettingStore()
|
||||
const commandStore = useCommandStore()
|
||||
@@ -138,20 +147,89 @@ const hasPendingTasks = computed(() => queueCountStore.count.value > 1)
|
||||
const queuePrompt = (e: MouseEvent) => {
|
||||
app.queuePrompt(e.shiftKey ? -1 : 0, batchCount.value)
|
||||
}
|
||||
|
||||
const panelRef = ref<HTMLElement | null>(null)
|
||||
const dragHandleRef = ref<HTMLElement | null>(null)
|
||||
const storedPosition = useLocalStorage('Comfy.MenuPosition.Floating', {
|
||||
x: 0,
|
||||
y: 0
|
||||
})
|
||||
const { x, y, style, isDragging } = useDraggable(panelRef, {
|
||||
initialValue: { x: 0, y: 0 },
|
||||
handle: dragHandleRef,
|
||||
containerElement: document.body
|
||||
})
|
||||
|
||||
// Update storedPosition when x or y changes
|
||||
watch(
|
||||
[x, y],
|
||||
debounce(([newX, newY]) => {
|
||||
storedPosition.value = { x: newX, y: newY }
|
||||
}, 300)
|
||||
)
|
||||
|
||||
// Set initial position to bottom center
|
||||
const setInitialPosition = () => {
|
||||
if (x.value !== 0 || y.value !== 0) {
|
||||
return
|
||||
}
|
||||
if (storedPosition.value.x !== 0 || storedPosition.value.y !== 0) {
|
||||
x.value = storedPosition.value.x
|
||||
y.value = storedPosition.value.y
|
||||
return
|
||||
}
|
||||
if (panelRef.value) {
|
||||
const screenWidth = window.innerWidth
|
||||
const screenHeight = window.innerHeight
|
||||
const menuWidth = panelRef.value.offsetWidth
|
||||
const menuHeight = panelRef.value.offsetHeight
|
||||
|
||||
if (menuWidth === 0 || menuHeight === 0) {
|
||||
return
|
||||
}
|
||||
|
||||
x.value = (screenWidth - menuWidth) / 2
|
||||
y.value = screenHeight - menuHeight - 10 // 10px margin from bottom
|
||||
}
|
||||
}
|
||||
onMounted(setInitialPosition)
|
||||
watch(visible, (newVisible) => {
|
||||
if (newVisible) {
|
||||
nextTick(setInitialPosition)
|
||||
}
|
||||
})
|
||||
|
||||
const adjustMenuPosition = () => {
|
||||
if (panelRef.value) {
|
||||
const screenWidth = window.innerWidth
|
||||
const screenHeight = window.innerHeight
|
||||
const menuWidth = panelRef.value.offsetWidth
|
||||
const menuHeight = panelRef.value.offsetHeight
|
||||
|
||||
// Adjust x position if menu is off-screen horizontally
|
||||
x.value = clamp(x.value, 0, screenWidth - menuWidth)
|
||||
|
||||
// Adjust y position if menu is off-screen vertically
|
||||
y.value = clamp(y.value, 0, screenHeight - menuHeight)
|
||||
}
|
||||
}
|
||||
|
||||
useEventListener(window, 'resize', adjustMenuPosition)
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.app-menu {
|
||||
pointer-events: all;
|
||||
position: fixed;
|
||||
bottom: 10px;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
z-index: 1000;
|
||||
}
|
||||
|
||||
.app-menu.is-dragging {
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
:deep(.p-panel-content) {
|
||||
padding: 10px;
|
||||
@apply p-2;
|
||||
}
|
||||
|
||||
:deep(.p-panel-header) {
|
||||
|
||||
Reference in New Issue
Block a user