Files
ComfyUI_frontend/src/stores/workspace/rightSidePanelStore.ts
jaeone94 46c40c755e feat: node-specific error tab with selection-aware grouping and error overlay (#8956)
## Summary
Enhances the error panel with node-specific views: single-node selection
shows errors grouped by message in compact mode, container nodes
(subgraph/group) expose child errors via a badge and "See Error" button,
and a floating ErrorOverlay appears after execution failure with a
deduplicated summary and quick navigation to the errors tab.

## Changes
- **Consolidate error tab**: Remove `TabError.vue`; merge all error
display into `TabErrors.vue` and drop the separate `error` tab type from
`rightSidePanelStore`
- **Selection-aware grouping**: Single-node selection regroups errors by
message (not `class_type`) and renders `ErrorNodeCard` in compact mode
- **Container node support**: Detect child-node errors in subgraph/group
nodes via execution ID prefix matching; show error badge and "See Error"
button in `SectionWidgets`
- **ErrorOverlay**: New floating card shown after execution failure with
deduplicated error messages, "Dismiss" and "See Errors" actions;
`isErrorOverlayOpen` / `showErrorOverlay` / `dismissErrorOverlay` added
to `executionStore`
- **Refactor**: Centralize error ID collection in `executionStore`
(`allErrorExecutionIds`, `hasInternalErrorForNode`); split `errorGroups`
into `allErrorGroups` (unfiltered) and `tabErrorGroups`
(selection-filtered); move `ErrorOverlay` business logic into
`useErrorGroups`

## Review Focus
- `useErrorGroups.ts`: split into `allErrorGroups` / `tabErrorGroups`
and the new `filterBySelection` parameter flow
- `executionStore.ts`: `hasInternalErrorForNode` helper and
`allErrorExecutionIds` computed
- `ErrorOverlay.vue`: integration with `executionStore` overlay state
and `useErrorGroups`

## Screenshots
<img width="853" height="461" alt="image"
src="https://github.com/user-attachments/assets/a49ab620-4209-4ae7-b547-fba13da0c633"
/>
<img width="854" height="203" alt="image"
src="https://github.com/user-attachments/assets/c119da54-cd78-4e7a-8b7a-456cfd348f1d"
/>
<img width="497" height="361" alt="image"
src="https://github.com/user-attachments/assets/74b16161-cf45-454b-ae60-24922fe36931"
/>

---------

Co-authored-by: GitHub Action <action@github.com>
Co-authored-by: github-actions <github-actions@github.com>
2026-02-20 12:14:52 -08:00

98 lines
2.5 KiB
TypeScript

import { defineStore } from 'pinia'
import { computed, ref, watch } from 'vue'
import { useSettingStore } from '@/platform/settings/settingStore'
export type RightSidePanelTab =
| 'parameters'
| 'nodes'
| 'settings'
| 'info'
| 'subgraph'
| 'errors'
type RightSidePanelSection = 'advanced-inputs' | string
/**
* Store for managing the right side panel state.
* This panel displays properties and settings for selected nodes.
*/
export const useRightSidePanelStore = defineStore('rightSidePanel', () => {
const settingStore = useSettingStore()
const isLegacyMenu = computed(
() => settingStore.get('Comfy.UseNewMenu') === 'Disabled'
)
const isOpen = computed({
get: () =>
!isLegacyMenu.value && settingStore.get('Comfy.RightSidePanel.IsOpen'),
set: (value: boolean) =>
settingStore.set('Comfy.RightSidePanel.IsOpen', value)
})
const activeTab = ref<RightSidePanelTab>('parameters')
const isEditingSubgraph = computed(() => activeTab.value === 'subgraph')
const focusedSection = ref<RightSidePanelSection | null>(null)
/**
* Graph node ID to focus in the errors tab.
* Set by SectionWidgets when the user clicks "See Error", consumed and
* cleared by TabErrors after expanding the relevant error group.
*/
const focusedErrorNodeId = ref<string | null>(null)
const searchQuery = ref('')
// Auto-close panel when switching to legacy menu mode
watch(isLegacyMenu, (legacy) => {
if (legacy) {
void settingStore.set('Comfy.RightSidePanel.IsOpen', false)
}
})
function openPanel(tab?: RightSidePanelTab) {
if (isLegacyMenu.value) return
isOpen.value = true
if (tab) {
activeTab.value = tab
}
}
function closePanel() {
isOpen.value = false
}
function togglePanel() {
isOpen.value = !isOpen.value
}
/**
* Focus on a specific section in the right side panel.
* This will open the panel, switch to the parameters tab, and signal
* the component to expand and scroll to the section.
*/
function focusSection(section: RightSidePanelSection) {
openPanel('parameters')
focusedSection.value = section
}
/**
* Clear the focused section after it has been handled.
*/
function clearFocusedSection() {
focusedSection.value = null
}
return {
isOpen,
activeTab,
isEditingSubgraph,
focusedSection,
focusedErrorNodeId,
searchQuery,
openPanel,
closePanel,
togglePanel,
focusSection,
clearFocusedSection
}
})