mirror of
https://github.com/Comfy-Org/ComfyUI_frontend.git
synced 2026-04-23 07:50:15 +00:00
rework minimap, toolbox, and menu designs with unified theming (#6038)
## Summary This PR redesigns the graph canvas interface components including minimap, toolbox, and menu systems with updated spacing, colors, and interaction patterns - using the design tokens directly from Figma, which can be used elsewhere going forward. There are some other changes to the designs, outlined [here](https://www.notion.so/comfy-org/Update-Minimap-Menu-v2-2886d73d365080e88e12f8df027019c0): - [x] Update/standardize the padding between viewport and toolbox - [x] Update toolbox component’s style to match the other floating menus style (border radius, height, padding and follow theme colors) - [x] Expose the minimap button - [x] Remove the focus button and delete it’s keybinding - [x] Group the hand and the default cursor buttons https://github.com/user-attachments/assets/92542e60-c32d-4a21-a6f6-e72837a70b17 ## Review Focus New CSS variables for cross-component theming consistency and CanvasModeSelector component extraction for improved code organization. ┆Issue is synchronized with this [Notion page](https://www.notion.so/PR-6038-rework-minimap-toolbox-and-menu-designs-with-unified-theming-28b6d73d36508191a0c6cf8036d965c4) by [Unito](https://www.unito.io) --------- Co-authored-by: github-actions <github-actions@github.com>
This commit is contained in:
@@ -1,118 +1,51 @@
|
||||
<template>
|
||||
<div
|
||||
v-if="visible"
|
||||
class="absolute right-2 bottom-[66px] z-1300 flex w-[250px] justify-center border-0! bg-inherit! md:right-11"
|
||||
class="absolute right-2 bottom-[66px] z-1300 flex w-[250px] justify-center border-0! bg-inherit!"
|
||||
>
|
||||
<div
|
||||
class="w-4/5 rounded-lg border border-gray-200 bg-white p-4 shadow-lg dark-theme:border-gray-700 dark-theme:bg-[#2b2b2b]"
|
||||
class="w-4/5 rounded-lg border border-node-border bg-interface-panel-surface p-2 text-text-primary shadow-lg select-none"
|
||||
:style="filteredMinimapStyles"
|
||||
@click.stop
|
||||
>
|
||||
<div>
|
||||
<Button
|
||||
severity="secondary"
|
||||
text
|
||||
:pt="{
|
||||
root: {
|
||||
class:
|
||||
'flex items-center justify-between cursor-pointer p-2 rounded w-full text-left hover:bg-transparent! focus:bg-transparent! active:bg-transparent!'
|
||||
},
|
||||
label: {
|
||||
class: 'flex flex-col items-start w-full'
|
||||
}
|
||||
}"
|
||||
<div class="flex flex-col gap-1">
|
||||
<div
|
||||
class="flex cursor-pointer items-center justify-between rounded px-3 py-2 text-sm hover:bg-node-component-surface-hovered"
|
||||
@mousedown="startRepeat('Comfy.Canvas.ZoomIn')"
|
||||
@mouseup="stopRepeat"
|
||||
@mouseleave="stopRepeat"
|
||||
>
|
||||
<template #default>
|
||||
<span class="block text-sm font-medium">{{
|
||||
$t('graphCanvasMenu.zoomIn')
|
||||
}}</span>
|
||||
<span class="block text-sm text-gray-500">{{
|
||||
zoomInCommandText
|
||||
}}</span>
|
||||
</template>
|
||||
</Button>
|
||||
<span class="font-medium">{{ $t('graphCanvasMenu.zoomIn') }}</span>
|
||||
<span class="text-[9px] text-text-primary">{{
|
||||
zoomInCommandText
|
||||
}}</span>
|
||||
</div>
|
||||
|
||||
<Button
|
||||
severity="secondary"
|
||||
text
|
||||
:pt="{
|
||||
root: {
|
||||
class:
|
||||
'flex items-center justify-between cursor-pointer p-2 rounded w-full text-left hover:bg-transparent! focus:bg-transparent! active:bg-transparent!'
|
||||
},
|
||||
label: {
|
||||
class: 'flex flex-col items-start w-full'
|
||||
}
|
||||
}"
|
||||
<div
|
||||
class="flex cursor-pointer items-center justify-between rounded px-3 py-2 text-sm hover:bg-node-component-surface-hovered"
|
||||
@mousedown="startRepeat('Comfy.Canvas.ZoomOut')"
|
||||
@mouseup="stopRepeat"
|
||||
@mouseleave="stopRepeat"
|
||||
>
|
||||
<template #default>
|
||||
<span class="block text-sm font-medium">{{
|
||||
$t('graphCanvasMenu.zoomOut')
|
||||
}}</span>
|
||||
<span class="block text-sm text-gray-500">{{
|
||||
zoomOutCommandText
|
||||
}}</span>
|
||||
</template>
|
||||
</Button>
|
||||
<span class="font-medium">{{ $t('graphCanvasMenu.zoomOut') }}</span>
|
||||
<span class="text-[9px] text-text-primary">{{
|
||||
zoomOutCommandText
|
||||
}}</span>
|
||||
</div>
|
||||
|
||||
<Button
|
||||
severity="secondary"
|
||||
text
|
||||
:pt="{
|
||||
root: {
|
||||
class:
|
||||
'flex items-center justify-between cursor-pointer p-2 rounded w-full text-left hover:bg-transparent! focus:bg-transparent! active:bg-transparent!'
|
||||
},
|
||||
label: {
|
||||
class: 'flex flex-col items-start w-full'
|
||||
}
|
||||
}"
|
||||
<div
|
||||
class="flex cursor-pointer items-center justify-between rounded px-3 py-2 text-sm hover:bg-node-component-surface-hovered"
|
||||
@click="executeCommand('Comfy.Canvas.FitView')"
|
||||
>
|
||||
<template #default>
|
||||
<span class="block text-sm font-medium">{{
|
||||
$t('zoomControls.zoomToFit')
|
||||
}}</span>
|
||||
<span class="block text-sm text-gray-500">{{
|
||||
zoomToFitCommandText
|
||||
}}</span>
|
||||
</template>
|
||||
</Button>
|
||||
<hr class="mb-1 border-[#E1DED5] dark-theme:border-[#2E3037]" />
|
||||
<Button
|
||||
severity="secondary"
|
||||
text
|
||||
data-testid="toggle-minimap-button"
|
||||
:pt="{
|
||||
root: {
|
||||
class:
|
||||
'flex items-center justify-between cursor-pointer p-2 rounded w-full text-left hover:bg-transparent! focus:bg-transparent! active:bg-transparent!'
|
||||
},
|
||||
label: {
|
||||
class: 'flex flex-col items-start w-full'
|
||||
}
|
||||
}"
|
||||
@click="executeCommand('Comfy.Canvas.ToggleMinimap')"
|
||||
>
|
||||
<template #default>
|
||||
<span class="block text-sm font-medium">{{
|
||||
minimapToggleText
|
||||
}}</span>
|
||||
<span class="block text-sm text-gray-500">{{
|
||||
showMinimapCommandText
|
||||
}}</span>
|
||||
</template>
|
||||
</Button>
|
||||
<hr class="mt-1 border-[#E1DED5] dark-theme:border-[#2E3037]" />
|
||||
<span class="font-medium">{{ $t('zoomControls.zoomToFit') }}</span>
|
||||
<span class="text-[9px] text-text-primary">{{
|
||||
zoomToFitCommandText
|
||||
}}</span>
|
||||
</div>
|
||||
|
||||
<div
|
||||
ref="zoomInputContainer"
|
||||
class="zoomInputContainer flex items-center rounded bg-[#E7E6E6] p-2 px-2 focus-within:bg-[#F3F3F3] dark-theme:bg-[#8282821A]"
|
||||
class="zoomInputContainer flex items-center gap-1 rounded bg-input-surface p-2"
|
||||
>
|
||||
<InputNumber
|
||||
ref="zoomInput"
|
||||
@@ -122,12 +55,12 @@
|
||||
:show-buttons="false"
|
||||
:use-grouping="false"
|
||||
:unstyled="true"
|
||||
input-class="flex-1 bg-transparent border-none outline-hidden text-sm shadow-none my-0 "
|
||||
input-class="bg-transparent border-none outline-hidden text-sm shadow-none my-0 w-full"
|
||||
fluid
|
||||
@input="applyZoom"
|
||||
@keyup.enter="applyZoom"
|
||||
/>
|
||||
<span class="-ml-4 text-sm text-gray-500">%</span>
|
||||
<span class="flex-shrink-0 text-sm text-text-primary">%</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -136,18 +69,14 @@
|
||||
|
||||
<script setup lang="ts">
|
||||
import type { InputNumberInputEvent } from 'primevue'
|
||||
import { Button, InputNumber } from 'primevue'
|
||||
import { InputNumber } from 'primevue'
|
||||
import { computed, nextTick, ref, watch } from 'vue'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
|
||||
import { useSettingStore } from '@/platform/settings/settingStore'
|
||||
import { useCanvasStore } from '@/renderer/core/canvas/canvasStore'
|
||||
import { useMinimap } from '@/renderer/extensions/minimap/composables/useMinimap'
|
||||
import { useCommandStore } from '@/stores/commandStore'
|
||||
|
||||
const { t } = useI18n()
|
||||
const minimap = useMinimap()
|
||||
const settingStore = useSettingStore()
|
||||
const commandStore = useCommandStore()
|
||||
const canvasStore = useCanvasStore()
|
||||
const { formatKeySequence } = useCommandStore()
|
||||
@@ -158,19 +87,8 @@ interface Props {
|
||||
|
||||
const props = defineProps<Props>()
|
||||
|
||||
const emit = defineEmits<{
|
||||
close: []
|
||||
}>()
|
||||
|
||||
const interval = ref<number | null>(null)
|
||||
|
||||
// Computed properties for reactive states
|
||||
const minimapToggleText = computed(() =>
|
||||
settingStore.get('Comfy.Minimap.Visible')
|
||||
? t('zoomControls.hideMinimap')
|
||||
: t('zoomControls.showMinimap')
|
||||
)
|
||||
|
||||
const applyZoom = (val: InputNumberInputEvent) => {
|
||||
const inputValue = val.value as number
|
||||
if (isNaN(inputValue) || inputValue < 1 || inputValue > 1000) {
|
||||
@@ -181,9 +99,6 @@ const applyZoom = (val: InputNumberInputEvent) => {
|
||||
|
||||
const executeCommand = (command: string) => {
|
||||
void commandStore.execute(command)
|
||||
if (command === 'Comfy.Canvas.ToggleMinimap') {
|
||||
emit('close')
|
||||
}
|
||||
}
|
||||
|
||||
const startRepeat = (command: string) => {
|
||||
@@ -215,9 +130,6 @@ const zoomOutCommandText = computed(() =>
|
||||
const zoomToFitCommandText = computed(() =>
|
||||
formatKeySequence(commandStore.getCommand('Comfy.Canvas.FitView'))
|
||||
)
|
||||
const showMinimapCommandText = computed(() =>
|
||||
formatKeySequence(commandStore.getCommand('Comfy.Canvas.ToggleMinimap'))
|
||||
)
|
||||
const zoomInput = ref<InstanceType<typeof InputNumber> | null>(null)
|
||||
const zoomInputContainer = ref<HTMLDivElement | null>(null)
|
||||
|
||||
@@ -236,10 +148,6 @@ watch(
|
||||
</script>
|
||||
<style>
|
||||
.zoomInputContainer:focus-within {
|
||||
border: 1px solid rgb(204 204 204);
|
||||
}
|
||||
|
||||
.dark-theme .zoomInputContainer:focus-within {
|
||||
border: 1px solid rgb(204 204 204);
|
||||
border: 1px solid var(--color-pure-white);
|
||||
}
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user