fix: dim compound containers when no descendants executed in overlay

CompoundNode (circuit breaker, choice, etc.) now renders at 0.35
opacity when the overlay is active but neither the compound itself
nor any of its diagram descendants appear in the execution overlay.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
hsiegeln
2026-03-30 20:13:40 +02:00
parent 26de222884
commit 3091754b0f

View File

@@ -71,6 +71,10 @@ export function CompoundNode({
const isGated = ownState?.filterMatched === false || ownState?.duplicateMessage === true;
const effectiveColor = isGated ? 'var(--amber)' : color;
// Dim compound when overlay is active but neither the compound nor any
// descendant was executed in the current iteration.
const isSkipped = overlayActive && !ownState && !hasExecutedDescendant(node, executionOverlay);
// _TRY_BODY / _CB_MAIN: transparent wrapper — no header, no border, just layout
if (node.type === '_TRY_BODY' || node.type === '_CB_MAIN') {
return (
@@ -85,7 +89,7 @@ export function CompoundNode({
if (node.type === '_CB_FALLBACK') {
const fallbackColor = '#7C3AED'; // EIP purple
return (
<g data-node-id={node.id} transform={`translate(${x}, ${y})`}>
<g data-node-id={node.id} transform={`translate(${x}, ${y})`} opacity={isSkipped ? 0.35 : undefined}>
<rect x={0} y={0} width={w} height={h} rx={CORNER_RADIUS}
fill={fallbackColor} fillOpacity={0.06} />
<rect x={0} y={0} width={w} height={h} rx={CORNER_RADIUS}
@@ -106,7 +110,7 @@ export function CompoundNode({
: (node.label ? `finally: ${node.label}` : 'finally');
return (
<g data-node-id={node.id} transform={`translate(${x}, ${y})`}>
<g data-node-id={node.id} transform={`translate(${x}, ${y})`} opacity={isSkipped ? 0.35 : undefined}>
{/* Tinted background */}
<rect x={0} y={0} width={w} height={h} rx={CORNER_RADIUS}
fill={color} fillOpacity={0.06} />
@@ -126,7 +130,7 @@ export function CompoundNode({
// Default compound rendering (DO_TRY, EIP_CHOICE, EIP_FILTER, EIP_IDEMPOTENT_CONSUMER, etc.)
const containerFill = isGated ? 'var(--amber-bg)' : 'white';
return (
<g data-node-id={node.id} transform={`translate(${x}, ${y})`}>
<g data-node-id={node.id} transform={`translate(${x}, ${y})`} opacity={isSkipped ? 0.35 : undefined}>
{/* Container body */}
<rect
x={0}
@@ -268,3 +272,15 @@ function collectIds(nodes: DiagramNodeType[], set: Set<string>) {
if (n.children) collectIds(n.children, set);
}
}
function hasExecutedDescendant(
node: DiagramNodeType,
overlay?: Map<string, NodeExecutionState>,
): boolean {
if (!overlay || !node.children) return false;
for (const child of node.children) {
if (child.id && overlay.has(child.id)) return true;
if (child.children && hasExecutedDescendant(child, overlay)) return true;
}
return false;
}