Files
Comfyui-Workflow-Snapshot-M…/docs/plans/2026-04-03-ux-rework-plan.md
Ethanfel cf8208c540 Add UX rework implementation plan
5 tasks: hide branching, skip move autosaves, compute diff at capture,
show diff in sidebar tooltip, show diff in timeline tooltip.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-03 00:09:11 +02:00

10 KiB
Raw Permalink Blame History

UX Rework Implementation Plan

For Claude: REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task.

Goal: Three focused UX improvements: hide branching UI, skip move-only autosaves, and show specific diff details on hover.

Architecture: All changes are in js/snapshot_manager.js. No backend changes needed. Diff summary is computed at capture time and stored in snapshot metadata so hover display is instant (no extra fetch).

Tech Stack: Vanilla JS, ComfyUI extension API, existing computeDetailedDiff() function (line 485).


Task 1: Hide branching UI

Files:

  • Modify: js/snapshot_manager.js:27 (branchingDefault)
  • Modify: js/snapshot_manager.js:350-354 (isBranchingEnabled)
  • Modify: js/snapshot_manager.js:2847-2866 (branchToggleBtn)

Step 1: Add BRANCHING_ENABLED constant

At the very top of the file (after the opening comment block, around line 1-30), add this constant near the other state variables:

const BRANCHING_ENABLED = false;

Place it just before line 27 (let branchingDefault = true;).

Step 2: Short-circuit isBranchingEnabled()

Current code at line 350:

function isBranchingEnabled(wk) {
    if (!wk) wk = getEffectiveWorkflowKey();
    if (workflowBranchOverrides.has(wk)) return workflowBranchOverrides.get(wk);
    return branchingDefault;
}

Add an early return at the top of the function:

function isBranchingEnabled(wk) {
    if (!BRANCHING_ENABLED) return false;
    if (!wk) wk = getEffectiveWorkflowKey();
    if (workflowBranchOverrides.has(wk)) return workflowBranchOverrides.get(wk);
    return branchingDefault;
}

This makes all 14 existing isBranchingEnabled() callsites automatically behave as if branching is off — no other changes needed in capture, sidebar, or timeline code.

Step 3: Hide the branch toggle button in the sidebar

The button is created at line 2847 and appended at line 2866. Hide it:

Current (line 2847):

const branchToggleBtn = document.createElement("button");
branchToggleBtn.className = "snap-filter-auto-btn" + (isBranchingEnabled() ? " active" : "");

Change to:

const branchToggleBtn = document.createElement("button");
branchToggleBtn.className = "snap-filter-auto-btn" + (isBranchingEnabled() ? " active" : "");
branchToggleBtn.style.display = "none";

Step 4: Verify manually in browser

  • Open ComfyUI, open snapshot manager sidebar
  • Confirm "Branch" button is not visible
  • Create 2-3 snapshots, confirm no branch navigator (< 1/2 >) appears
  • Confirm timeline has no expand button

Step 5: Commit

git add js/snapshot_manager.js
git commit -m "Hide branching UI (BRANCHING_ENABLED = false)"

Task 2: Skip move-only autosaves

Files:

  • Modify: js/snapshot_manager.js:1459-1460

Step 1: Add move filter in _captureSnapshotInner

Current code at lines 1458-1460:

const prevGraph = lastGraphDataMap.get(workflowKey);
const changeType = detectChangeType(prevGraph, graphData);

// Determine parentId for branching

Add one line after the changeType computation:

const prevGraph = lastGraphDataMap.get(workflowKey);
const changeType = detectChangeType(prevGraph, graphData);
if (changeType === "move") return false;

// Determine parentId for branching

Step 2: Verify manually in browser

  • Open ComfyUI, move several nodes around
  • Confirm no new snapshots appear in the sidebar/timeline while moving
  • Add a node → confirm a snapshot IS created
  • Change a parameter → confirm a snapshot IS created

Step 3: Commit

git add js/snapshot_manager.js
git commit -m "Skip autosave for move-only changes"

Task 3: Store diff summary at capture time

Files:

  • Modify: js/snapshot_manager.js:614 (after computeDetailedDiff, add new helper)
  • Modify: js/snapshot_manager.js:1471-1481 (record construction in _captureSnapshotInner)
  • Modify: js/snapshot_manager.js:1550-1562 (record construction in captureNodeSnapshot)

Step 1: Add computeCaptureMetaDiff() and formatCaptureDiffLines() helpers

Insert these two functions right after computeDetailedDiff ends (after line 614, before the SVG section comment at line 616):

// Compact diff stored in snapshot metadata for hover display
function computeCaptureMetaDiff(prevGraph, currGraph) {
    if (!prevGraph || !currGraph) return null;
    const diff = computeDetailedDiff(prevGraph, currGraph);
    const result = {};
    if (diff.addedNodes.length > 0)
        result.added = diff.addedNodes.map(n => n.title);
    if (diff.removedNodes.length > 0)
        result.removed = diff.removedNodes.map(n => n.title);
    // Nodes with param/property changes (ignore pure position/size changes)
    const paramChanged = diff.modifiedNodes.filter(n =>
        n.changes.widgetValues || n.changes.properties || n.changes.title || n.changes.mode
    );
    if (paramChanged.length > 0)
        result.params = paramChanged.map(n => {
            const count = (n.changes.widgetValues?.length ?? 0) + (n.changes.properties?.length ?? 0);
            return count > 0 ? `${n.title} (${count} value${count > 1 ? "s" : ""})` : n.title;
        });
    if (diff.addedLinks.length > 0 || diff.removedLinks.length > 0)
        result.links = { added: diff.addedLinks.length, removed: diff.removedLinks.length };
    return Object.keys(result).length > 0 ? result : null;
}

function formatCaptureDiffLines(captureDiff) {
    if (!captureDiff) return [];
    const lines = [];
    if (captureDiff.added?.length)
        lines.push(`+ ${captureDiff.added.join(", ")}`);
    if (captureDiff.removed?.length)
        lines.push(` ${captureDiff.removed.join(", ")}`);
    if (captureDiff.params?.length)
        lines.push(`~ ${captureDiff.params.join(", ")}`);
    if (captureDiff.links) {
        const parts = [];
        if (captureDiff.links.added) parts.push(`+${captureDiff.links.added} link${captureDiff.links.added > 1 ? "s" : ""}`);
        if (captureDiff.links.removed) parts.push(`${captureDiff.links.removed} link${captureDiff.links.removed > 1 ? "s" : ""}`);
        if (parts.length) lines.push(parts.join(", "));
    }
    return lines;
}

Step 2: Add captureDiff to record in _captureSnapshotInner

Current record construction at lines 1471-1481:

const record = {
    id: generateId(),
    workflowKey,
    timestamp: Date.now(),
    label,
    nodeCount: nodes.length,
    graphData,
    locked: false,
    changeType,
    parentId,
};

Add captureDiff field:

const captureDiff = computeCaptureMetaDiff(prevGraph, graphData);
const record = {
    id: generateId(),
    workflowKey,
    timestamp: Date.now(),
    label,
    nodeCount: nodes.length,
    graphData,
    locked: false,
    changeType,
    parentId,
    ...(captureDiff ? { captureDiff } : {}),
};

Step 3: Same for captureNodeSnapshot

Current record construction at lines 1550-1562:

const record = {
    id: generateId(),
    workflowKey,
    timestamp: Date.now(),
    label,
    nodeCount: nodes.length,
    graphData,
    locked: false,
    source: "node",
    changeType,
    parentId,
    ...(thumbnail ? { thumbnail } : {}),
};

Change to:

const captureDiff = computeCaptureMetaDiff(prevGraph, graphData);
const record = {
    id: generateId(),
    workflowKey,
    timestamp: Date.now(),
    label,
    nodeCount: nodes.length,
    graphData,
    locked: false,
    source: "node",
    changeType,
    parentId,
    ...(captureDiff ? { captureDiff } : {}),
    ...(thumbnail ? { thumbnail } : {}),
};

Step 4: Commit

git add js/snapshot_manager.js
git commit -m "Compute and store diff summary at capture time"

Task 4: Show diff in sidebar hover tooltip

Files:

  • Modify: js/snapshot_manager.js:3573-3603 (mouseenter handler in sidebar)

Step 1: Add diff lines to tooltip

Current mouseenter callback (lines 3572-3608) renders an SVG or thumbnail then positions/shows the tooltip. After the SVG/thumbnail is appended (right before the rect / positioning block), add diff lines:

Locate this block in the mouseenter callback:

                    if (!tooltipTimer) return;
                    const svg = getCachedSVG(rec.id, graphData, { width: 240, height: 180 });
                    if (!svg) return;
                    tooltip.appendChild(svg);
                }
                const rect = item.getBoundingClientRect();

Change to:

                    if (!tooltipTimer) return;
                    const svg = getCachedSVG(rec.id, graphData, { width: 240, height: 180 });
                    if (!svg) return;
                    tooltip.appendChild(svg);
                }
                // Diff summary lines
                const diffLines = formatCaptureDiffLines(rec.captureDiff);
                if (diffLines.length > 0) {
                    const diffEl = document.createElement("div");
                    diffEl.style.cssText = "margin-top:6px;font-size:11px;line-height:1.5;color:#ccc;white-space:pre;";
                    diffEl.textContent = diffLines.join("\n");
                    tooltip.appendChild(diffEl);
                }
                const rect = item.getBoundingClientRect();

Step 2: Verify manually in browser

  • Create a snapshot by adding a node → hover it in sidebar → tooltip shows SVG preview + diff lines like + KSampler
  • Create a snapshot by changing a param → hover it → tooltip shows ~ KSampler (1 value)
  • Hover an old snapshot without captureDiff → tooltip shows SVG only (no crash)

Step 3: Commit

git add js/snapshot_manager.js
git commit -m "Show diff summary in sidebar hover tooltip"

Task 5: Show diff in timeline marker tooltip

Files:

  • Modify: js/snapshot_manager.js:3715-3717 (buildMarker tip construction)

Step 1: Append diff lines to marker title

Current code at lines 3715-3717:

        let tip = `${rec.label}${formatTime(rec.timestamp)}\n${iconInfo.label}`;
        if (rec.notes) tip += `\n${rec.notes}`;
        marker.title = tip;

Change to:

        let tip = `${rec.label}${formatTime(rec.timestamp)}\n${iconInfo.label}`;
        const diffLines = formatCaptureDiffLines(rec.captureDiff);
        if (diffLines.length > 0) tip += `\n${diffLines.join("\n")}`;
        if (rec.notes) tip += `\n${rec.notes}`;
        marker.title = tip;

Step 2: Verify manually in browser

  • Hover a timeline marker → native tooltip shows label, time, change type, then diff lines

Step 3: Commit

git add js/snapshot_manager.js
git commit -m "Show diff summary in timeline marker tooltip"