mirror of
https://github.com/Comfy-Org/ComfyUI_frontend.git
synced 2026-04-24 00:09:32 +00:00
New bottom button and badges (#8603)
- "Enter Subgraph" "Show advanced inputs" and a new "show node Errors" button now use a combined button design at the bottom of the node. - A new "Errors" tab is added to the right side panel - After a failed queue, the label of an invalid widget is now red. - Badges other than price are now displayed on the bottom of the node. - Price badge will now truncate from the first space, prioritizing the sizing of the node title - An indicator for the node resize handle is now displayed while mousing over the node. <img width="669" height="233" alt="image" src="https://github.com/user-attachments/assets/53b3b59c-830b-474d-8f20-07f557124af7" />  --------- Co-authored-by: github-actions <github-actions@github.com>
This commit is contained in:
@@ -14,11 +14,13 @@ import { SubgraphNode } from '@/lib/litegraph/src/litegraph'
|
||||
import type { LGraphNode } from '@/lib/litegraph/src/litegraph'
|
||||
import { useSettingStore } from '@/platform/settings/settingStore'
|
||||
import { useCanvasStore } from '@/renderer/core/canvas/canvasStore'
|
||||
import { useExecutionStore } from '@/stores/executionStore'
|
||||
import { useRightSidePanelStore } from '@/stores/workspace/rightSidePanelStore'
|
||||
import type { RightSidePanelTab } from '@/stores/workspace/rightSidePanelStore'
|
||||
import { resolveNodeDisplayName } from '@/utils/nodeTitleUtil'
|
||||
import { cn } from '@/utils/tailwindUtil'
|
||||
|
||||
import TabError from './TabError.vue'
|
||||
import TabInfo from './info/TabInfo.vue'
|
||||
import TabGlobalParameters from './parameters/TabGlobalParameters.vue'
|
||||
import TabNodes from './parameters/TabNodes.vue'
|
||||
@@ -33,6 +35,7 @@ import {
|
||||
import SubgraphEditor from './subgraph/SubgraphEditor.vue'
|
||||
|
||||
const canvasStore = useCanvasStore()
|
||||
const executionStore = useExecutionStore()
|
||||
const rightSidePanelStore = useRightSidePanelStore()
|
||||
const settingStore = useSettingStore()
|
||||
const { t } = useI18n()
|
||||
@@ -87,10 +90,25 @@ function closePanel() {
|
||||
type RightSidePanelTabList = Array<{
|
||||
label: () => string
|
||||
value: RightSidePanelTab
|
||||
icon?: string
|
||||
}>
|
||||
|
||||
//FIXME all errors if nothing selected?
|
||||
const selectedNodeErrors = computed(() =>
|
||||
selectedNodes.value
|
||||
.map((node) => executionStore.getNodeErrors(`${node.id}`))
|
||||
.filter((nodeError) => !!nodeError)
|
||||
)
|
||||
|
||||
const tabs = computed<RightSidePanelTabList>(() => {
|
||||
const list: RightSidePanelTabList = []
|
||||
if (selectedNodeErrors.value.length) {
|
||||
list.push({
|
||||
label: () => t('g.error'),
|
||||
value: 'error',
|
||||
icon: 'icon-[lucide--octagon-alert] bg-node-stroke-error ml-1'
|
||||
})
|
||||
}
|
||||
|
||||
list.push({
|
||||
label: () =>
|
||||
@@ -271,6 +289,7 @@ function handleProxyWidgetsUpdate(value: ProxyWidgetsProperty) {
|
||||
:value="tab.value"
|
||||
>
|
||||
{{ tab.label() }}
|
||||
<i v-if="tab.icon" :class="cn(tab.icon, 'size-4')" />
|
||||
</Tab>
|
||||
</TabList>
|
||||
</nav>
|
||||
@@ -288,6 +307,7 @@ function handleProxyWidgetsUpdate(value: ProxyWidgetsProperty) {
|
||||
:node="selectedSingleNode"
|
||||
/>
|
||||
<template v-else>
|
||||
<TabError v-if="activeTab === 'error'" :errors="selectedNodeErrors" />
|
||||
<TabSubgraphInputs
|
||||
v-if="activeTab === 'parameters' && isSingleSubgraphNode"
|
||||
:node="selectedSingleNode as SubgraphNode"
|
||||
|
||||
30
src/components/rightSidePanel/TabError.vue
Normal file
30
src/components/rightSidePanel/TabError.vue
Normal file
@@ -0,0 +1,30 @@
|
||||
<script setup lang="ts">
|
||||
import { useI18n } from 'vue-i18n'
|
||||
|
||||
import Button from '@/components/ui/button/Button.vue'
|
||||
import { useCopyToClipboard } from '@/composables/useCopyToClipboard'
|
||||
import type { NodeError } from '@/schemas/apiSchema'
|
||||
|
||||
const { t } = useI18n()
|
||||
|
||||
defineProps<{
|
||||
errors: NodeError[]
|
||||
}>()
|
||||
const { copyToClipboard } = useCopyToClipboard()
|
||||
</script>
|
||||
<template>
|
||||
<div class="m-4">
|
||||
<Button class="w-full" @click="copyToClipboard(JSON.stringify(errors))">
|
||||
{{ t('g.copy') }}
|
||||
<i class="icon-[lucide--copy] size-4" />
|
||||
</Button>
|
||||
</div>
|
||||
<div
|
||||
v-for="(error, index) in errors.flatMap((ne) => ne.errors)"
|
||||
:key="index"
|
||||
class="px-2"
|
||||
>
|
||||
<h3 class="text-error" v-text="error.message" />
|
||||
<div class="text-muted-foreground" v-text="error.details" />
|
||||
</div>
|
||||
</template>
|
||||
Reference in New Issue
Block a user