Skip to content

Commit ddb3a0b

Browse files
christian-byrnegithub-actions
andauthored
fix Vue node opacity conditions (user node opacity, bypass state, muted state) (#6022)
## Summary Fixed Vue node opacity calculation to properly combine global opacity setting with muted/bypassed state opacity. **Root Cause**: When global opacity setting was added as inline style (481aa82), it began overriding CSS `opacity-50` classes due to higher specificity. **Solution**: Modified `nodeOpacity` computed property to calculate effective opacity as `globalOpacity * 0.5` for muted/bypassed states, removing conflicting CSS classes. ## Changes - **What**: Fixed [CSS specificity conflict](https://developer.mozilla.org/en-US/docs/Web/CSS/Specificity) where inline `opacity` style overrode `opacity-50` classes for muted/bypassed nodes - **Breaking**: None - restores intended opacity behavior ## Review Focus Multiplicative opacity calculation ensuring muted/bypassed nodes apply 0.5 opacity on top of global opacity setting rather than being overridden by it. ┆Issue is synchronized with this [Notion page](https://www.notion.so/PR-6022-fix-Vue-node-opacity-conditions-user-node-opacity-bypass-state-muted-state-2896d73d365081c290f1da37c195c2f5) by [Unito](https://www.unito.io) --------- Co-authored-by: github-actions <[email protected]>
1 parent 5773df6 commit ddb3a0b

File tree

5 files changed

+24
-19
lines changed

5 files changed

+24
-19
lines changed

browser_tests/tests/vueNodes/nodeStates/bypass.spec.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,9 @@ test.describe('Vue Node Bypass', () => {
2020

2121
const checkpointNode = comfyPage.vueNodes.getNodeByTitle('Load Checkpoint')
2222
await expect(checkpointNode).toHaveClass(BYPASS_CLASS)
23+
await expect(comfyPage.canvas).toHaveScreenshot(
24+
'vue-node-bypassed-state.png'
25+
)
2326

2427
await comfyPage.page.keyboard.press(BYPASS_HOTKEY)
2528
await expect(checkpointNode).not.toHaveClass(BYPASS_CLASS)
77.4 KB
Loading

browser_tests/tests/vueNodes/nodeStates/mute.spec.ts

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import {
44
} from '../../../fixtures/ComfyPage'
55

66
const MUTE_HOTKEY = 'Control+m'
7-
const MUTE_CLASS = /opacity-50/
7+
const MUTE_OPACITY = '0.5'
88

99
test.describe('Vue Node Mute', () => {
1010
test.beforeEach(async ({ comfyPage }) => {
@@ -19,10 +19,11 @@ test.describe('Vue Node Mute', () => {
1919
await comfyPage.page.keyboard.press(MUTE_HOTKEY)
2020

2121
const checkpointNode = comfyPage.vueNodes.getNodeByTitle('Load Checkpoint')
22-
await expect(checkpointNode).toHaveClass(MUTE_CLASS)
22+
await expect(checkpointNode).toHaveCSS('opacity', MUTE_OPACITY)
23+
await expect(comfyPage.canvas).toHaveScreenshot('vue-node-muted-state.png')
2324

2425
await comfyPage.page.keyboard.press(MUTE_HOTKEY)
25-
await expect(checkpointNode).not.toHaveClass(MUTE_CLASS)
26+
await expect(checkpointNode).not.toHaveCSS('opacity', MUTE_OPACITY)
2627
})
2728

2829
test('should allow toggling mute on multiple selected nodes with hotkey', async ({
@@ -35,11 +36,11 @@ test.describe('Vue Node Mute', () => {
3536
const ksamplerNode = comfyPage.vueNodes.getNodeByTitle('KSampler')
3637

3738
await comfyPage.page.keyboard.press(MUTE_HOTKEY)
38-
await expect(checkpointNode).toHaveClass(MUTE_CLASS)
39-
await expect(ksamplerNode).toHaveClass(MUTE_CLASS)
39+
await expect(checkpointNode).toHaveCSS('opacity', MUTE_OPACITY)
40+
await expect(ksamplerNode).toHaveCSS('opacity', MUTE_OPACITY)
4041

4142
await comfyPage.page.keyboard.press(MUTE_HOTKEY)
42-
await expect(checkpointNode).not.toHaveClass(MUTE_CLASS)
43-
await expect(ksamplerNode).not.toHaveClass(MUTE_CLASS)
43+
await expect(checkpointNode).not.toHaveCSS('opacity', MUTE_OPACITY)
44+
await expect(ksamplerNode).not.toHaveCSS('opacity', MUTE_OPACITY)
4445
})
4546
})
77.5 KB
Loading

src/renderer/extensions/vueNodes/components/LGraphNode.vue

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,9 @@
1919
outlineClass,
2020
{
2121
'animate-pulse': executing,
22-
'opacity-50 before:rounded-2xl before:pointer-events-none before:absolute before:bg-bypass/60 before:inset-0':
22+
'before:rounded-2xl before:pointer-events-none before:absolute before:bg-bypass/60 before:inset-0':
2323
bypassed,
24-
'opacity-50 before:rounded-2xl before:pointer-events-none before:absolute before:inset-0':
24+
'before:rounded-2xl before:pointer-events-none before:absolute before:inset-0':
2525
muted,
2626
'will-change-transform': isDragging
2727
},
@@ -174,26 +174,20 @@ const {
174174
175175
useVueElementTracking(() => nodeData.id, 'node')
176176
177-
const { selectedNodeIds } = storeToRefs(useCanvasStore())
178-
179-
// Inject transform state for coordinate conversion
180177
const transformState = inject(TransformStateKey)
181178
if (!transformState) {
182179
throw new Error(
183180
'TransformState must be provided for node resize functionality'
184181
)
185182
}
186183
187-
// Computed selection state - only this node re-evaluates when its selection changes
184+
const { selectedNodeIds } = storeToRefs(useCanvasStore())
188185
const isSelected = computed(() => {
189186
return selectedNodeIds.value.has(nodeData.id)
190187
})
191188
192-
// Use execution state composable
193189
const nodeLocatorId = computed(() => getLocatorIdFromNodeData(nodeData))
194190
const { executing, progress } = useNodeExecutionState(nodeLocatorId)
195-
196-
// Direct access to execution store for error state
197191
const executionStore = useExecutionStore()
198192
const hasExecutionError = computed(
199193
() => executionStore.lastExecutionErrorNodeId === nodeData.id
@@ -225,9 +219,16 @@ const nodeBodyBackgroundColor = computed(() => {
225219
)
226220
})
227221
228-
const nodeOpacity = computed(
229-
() => useSettingStore().get('Comfy.Node.Opacity') ?? 1
230-
)
222+
const nodeOpacity = computed(() => {
223+
const globalOpacity = useSettingStore().get('Comfy.Node.Opacity') ?? 1
224+
225+
// For muted/bypassed nodes, apply the 0.5 multiplier on top of global opacity
226+
if (bypassed.value || muted.value) {
227+
return globalOpacity * 0.5
228+
}
229+
230+
return globalOpacity
231+
})
231232
232233
// Use canvas interactions for proper wheel event handling and pointer event capture control
233234
const { handleWheel, shouldHandleNodePointerEvents } = useCanvasInteractions()

0 commit comments

Comments
 (0)