Skip to content

Conversation

@AustinMroz
Copy link
Collaborator

@AustinMroz AustinMroz commented Feb 4, 2026

  • "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.
image

resize

@AustinMroz AustinMroz requested review from a team as code owners February 4, 2026 04:26
@dosubot dosubot bot added the size:XL This PR changes 500-999 lines, ignoring generated files. label Feb 4, 2026
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Feb 4, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Aggregates execution-store node errors and exposes them as an Error tab in the right-side panel (new TabError component with copy-to-clipboard). Propagates per-widget/slot error flags, adds badge partitioning/composition (usePartitionedBadges + NodeBadges), and updates node/header UI and related tests.

Changes

Cohort / File(s) Summary
Right-side panel / Error UI
src/components/rightSidePanel/RightSidePanel.vue, src/components/rightSidePanel/TabError.vue, src/stores/workspace/rightSidePanelStore.ts
Adds execution-store aggregation of selected-node errors, exposes selectedNodeErrors, extends tabs with 'error', conditionally shows an Error tab and renders new TabError.vue (includes copy-to-clipboard).
Widget & slot error propagation
src/renderer/extensions/vueNodes/components/InputSlot.vue, src/renderer/extensions/vueNodes/components/NodeWidgets.vue
Introduces hasError prop on InputSlot; NodeWidgets computes per-widget hasError from executionStore and passes it down for styling and conditional classes.
Badge partitioning & rendering
src/renderer/extensions/vueNodes/composables/usePartitionedBadges.ts, src/renderer/extensions/vueNodes/components/NodeBadges.vue
Adds usePartitionedBadges composable to derive core/extension/pricing badge groups and hasComfyBadge; adds NodeBadges.vue to render partitioned badges with separators.
Node UI & header updates
src/renderer/extensions/vueNodes/components/LGraphNode.vue, src/renderer/extensions/vueNodes/components/NodeHeader.vue
Integrates partitioned badges into node UI, updates styling and resize handle, changes error-border behavior, removes subgraph-enter plumbing, and passes priceBadges into NodeHeader.
Pricing helper change
src/composables/node/usePriceBadge.ts
Adds exported isCreditsBadge and relaxes its badge parameter to accept `Partial
Types, tests & processed widgets
src/renderer/extensions/vueNodes/components/NodeWidgets.vue, src/renderer/extensions/vueNodes/components/LGraphNode.subgraph.test.ts
ProcessedWidget now includes hasError and explicit runtime fields; tests updated to mount LGraphNode, adjust typings/mocks, and remove subgraph-enter assertions.
Localization
src/locales/en/main.json
Adds g.enterSubgraph translation entry.

Sequence Diagram(s)

sequenceDiagram
    participant Node as LGraphNode
    participant Store as ExecutionStore
    participant Panel as RightSidePanel
    participant Tab as TabError

    Node->>Store: emit/update runtime errors
    Store-->>Panel: provide getNodeErrors(selectedNodes)
    Panel->>Panel: compute selectedNodeErrors (aggregate)
    alt selectedNodeErrors non-empty
        Panel->>Panel: append 'error' tab if missing
        Panel->>Panel: validate/set active tab (may switch to 'error')
        Panel->>Tab: render TabError with selectedNodeErrors
        Tab->>Tab: display errors and offer copy-to-clipboard
    else no errors
        Panel->>Panel: ensure active tab valid (fallback)
    end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

Suggested reviewers

  • christian-byrne
  • comfyui-wiki
  • DrJKL
  • KarryCharon
  • shinshin86

Poem

🐇
I nudged the badges, hopped through each bright dot,
Collected errors from the run and stored the lot,
A tab to show the traces, copy-clipped with glee,
Bugs in a basket, neat as can be,
Hoppity-hop — the panel sings, error-free (almost)!

🚥 Pre-merge checks | ❌ 3
❌ Failed checks (2 warnings, 1 inconclusive)
Check name Status Explanation Resolution
Description check ⚠️ Warning The description provides a detailed bullet-point list of changes and includes screenshots, but does not follow the required repository template structure with Summary, Changes, and Review Focus sections. Restructure the description to match the template: add a concise one-sentence Summary, organize Changes with What/Breaking/Dependencies subsections, and add Review Focus section highlighting critical design decisions.
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Title check ❓ Inconclusive The title is vague and uses non-descriptive phrasing that doesn't clearly convey the primary changes; 'New bottom button and badges' lacks specificity about functionality. Revise the title to be more specific about the main change, e.g., 'Consolidate node controls into bottom button bar with badge reorganization' or similar to better reflect the scope of changes.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch austin/node-bottom-button

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions
Copy link

github-actions bot commented Feb 4, 2026

Playwright: ✅ 523 passed, 0 failed · 2 flaky

📊 Browser Reports
  • chromium: View Report (✅ 511 / ❌ 0 / ⚠️ 2 / ⏭️ 8)
  • chromium-2x: View Report (✅ 2 / ❌ 0 / ⚠️ 0 / ⏭️ 0)
  • chromium-0.5x: View Report (✅ 1 / ❌ 0 / ⚠️ 0 / ⏭️ 0)
  • mobile-chrome: View Report (✅ 9 / ❌ 0 / ⚠️ 0 / ⏭️ 0)

@github-actions
Copy link

github-actions bot commented Feb 4, 2026

🎨 Storybook Build Status

Build completed successfully!

⏰ Completed at: 02/11/2026, 06:39:16 AM UTC

🔗 Links


🎉 Your Storybook is ready for review!

@github-actions
Copy link

github-actions bot commented Feb 4, 2026

Bundle Size Report

Summary

  • Raw size: 19.9 MB baseline 19.9 MB — 🔴 +4.55 kB
  • Gzip: 4.24 MB baseline 4.24 MB — 🔴 +222 B
  • Brotli: 3.29 MB baseline 3.29 MB — 🔴 +795 B
  • Bundles: 235 current • 235 baseline • 137 added / 137 removed

Category Glance
Graph Workspace 🔴 +19.6 kB (874 kB) · Data & Services 🟢 -15.1 kB (2.11 MB) · Other 🔴 +36 B (7.29 MB) · Vendor & Third-Party 🔴 +14 B (8.77 MB) · Panels & Settings 🟢 -1 B (454 kB) · Utilities & Hooks ⚪ 0 B (237 kB) · + 5 more

Per-category breakdown
App Entry Points — 22.2 kB (baseline 22.2 kB) • ⚪ 0 B

Main entry bundles and manifests

File Before After Δ Raw Δ Gzip Δ Brotli
assets/index-Brq0rCta.js (removed) 22.2 kB 🟢 -22.2 kB 🟢 -7.2 kB 🟢 -6.26 kB
assets/index-C4NuZVZE.js (new) 22.2 kB 🔴 +22.2 kB 🔴 +7.2 kB 🔴 +6.24 kB

Status: 1 added / 1 removed

Graph Workspace — 874 kB (baseline 854 kB) • 🔴 +19.6 kB

Graph editor runtime, canvas, workflow orchestration

File Before After Δ Raw Δ Gzip Δ Brotli
assets/GraphView-BikPPEtd.js (new) 874 kB 🔴 +874 kB 🔴 +188 kB 🔴 +144 kB
assets/GraphView-CFiNhHPd.js (removed) 854 kB 🟢 -854 kB 🟢 -184 kB 🟢 -140 kB

Status: 1 added / 1 removed

Views & Navigation — 68.8 kB (baseline 68.8 kB) • ⚪ 0 B

Top-level views, pages, and routed surfaces

File Before After Δ Raw Δ Gzip Δ Brotli
assets/CloudSurveyView-B2Z28aPg.js (removed) 15.4 kB 🟢 -15.4 kB 🟢 -3.3 kB 🟢 -2.81 kB
assets/CloudSurveyView-D-bSDHrN.js (new) 15.4 kB 🔴 +15.4 kB 🔴 +3.3 kB 🔴 +2.8 kB
assets/CloudLoginView-B0DaZmRm.js (new) 10.1 kB 🔴 +10.1 kB 🔴 +2.94 kB 🔴 +2.59 kB
assets/CloudLoginView-Cr62GGtl.js (removed) 10.1 kB 🟢 -10.1 kB 🟢 -2.94 kB 🟢 -2.59 kB
assets/UserCheckView-C6-YezEk.js (removed) 8.38 kB 🟢 -8.38 kB 🟢 -2.21 kB 🟢 -1.92 kB
assets/UserCheckView-CnzpUzrl.js (new) 8.38 kB 🔴 +8.38 kB 🔴 +2.21 kB 🔴 +1.92 kB
assets/CloudSignupView-BnwX3wwg.js (removed) 7.46 kB 🟢 -7.46 kB 🟢 -2.35 kB 🟢 -2.06 kB
assets/CloudSignupView-k2Zxasgo.js (new) 7.46 kB 🔴 +7.46 kB 🔴 +2.35 kB 🔴 +2.06 kB
assets/CloudLayoutView-B3IP7Du2.js (new) 6.45 kB 🔴 +6.45 kB 🔴 +2.11 kB 🔴 +1.83 kB
assets/CloudLayoutView-CLw6dpBG.js (removed) 6.45 kB 🟢 -6.45 kB 🟢 -2.11 kB 🟢 -1.83 kB
assets/CloudForgotPasswordView-BHtXWT-w.js (removed) 5.57 kB 🟢 -5.57 kB 🟢 -1.95 kB 🟢 -1.72 kB
assets/CloudForgotPasswordView-D3rlBKSf.js (new) 5.57 kB 🔴 +5.57 kB 🔴 +1.95 kB 🔴 +1.71 kB
assets/CloudAuthTimeoutView-b7o_z0zY.js (new) 4.92 kB 🔴 +4.92 kB 🔴 +1.78 kB 🔴 +1.56 kB
assets/CloudAuthTimeoutView-J5haBF_j.js (removed) 4.92 kB 🟢 -4.92 kB 🟢 -1.78 kB 🟢 -1.56 kB
assets/CloudSubscriptionRedirectView-B_CzXGuX.js (new) 4.72 kB 🔴 +4.72 kB 🔴 +1.79 kB 🔴 +1.58 kB
assets/CloudSubscriptionRedirectView-CDL4efaD.js (removed) 4.72 kB 🟢 -4.72 kB 🟢 -1.79 kB 🟢 -1.58 kB
assets/UserSelectView-BL3d82NQ.js (new) 4.46 kB 🔴 +4.46 kB 🔴 +1.62 kB 🔴 +1.45 kB
assets/UserSelectView-CSJxBEC3.js (removed) 4.46 kB 🟢 -4.46 kB 🟢 -1.62 kB 🟢 -1.45 kB
assets/layout-CFQY1ChE.js (new) 296 B 🔴 +296 B 🔴 +224 B 🔴 +192 B
assets/layout-Cv7zVMF7.js (removed) 296 B 🟢 -296 B 🟢 -222 B 🟢 -182 B
assets/CloudSorryContactSupportView-BDyiwiwq.js 1.02 kB 1.02 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B

Status: 10 added / 10 removed

Panels & Settings — 454 kB (baseline 454 kB) • 🟢 -1 B

Configuration panels, inspectors, and settings screens

File Before After Δ Raw Δ Gzip Δ Brotli
assets/WorkspacePanel-D5dimKSH.js (new) 26.8 kB 🔴 +26.8 kB 🔴 +5.63 kB 🔴 +4.94 kB
assets/WorkspacePanel-DyuciY8-.js (removed) 26.8 kB 🟢 -26.8 kB 🟢 -5.63 kB 🟢 -4.95 kB
assets/SecretsPanel-D8ezf2I9.js (removed) 21.5 kB 🟢 -21.5 kB 🟢 -5.29 kB 🟢 -4.64 kB
assets/SecretsPanel-JiAb1jJP.js (new) 21.5 kB 🔴 +21.5 kB 🔴 +5.29 kB 🔴 +4.63 kB
assets/LegacyCreditsPanel-OxuLctMS.js (removed) 20.8 kB 🟢 -20.8 kB 🟢 -5.61 kB 🟢 -4.95 kB
assets/LegacyCreditsPanel-DH92VdDY.js (new) 20.8 kB 🔴 +20.8 kB 🔴 +5.61 kB 🔴 +4.94 kB
assets/SubscriptionPanel-DXlG8jyI.js (removed) 18.7 kB 🟢 -18.7 kB 🟢 -4.76 kB 🟢 -4.22 kB
assets/SubscriptionPanel-q7X7p32G.js (new) 18.7 kB 🔴 +18.7 kB 🔴 +4.75 kB 🔴 +4.21 kB
assets/KeybindingPanel-B36n3hI_.js (removed) 12.6 kB 🟢 -12.6 kB 🟢 -3.63 kB 🟢 -3.22 kB
assets/KeybindingPanel-FDznrJ3H.js (new) 12.6 kB 🔴 +12.6 kB 🔴 +3.63 kB 🔴 +3.22 kB
assets/ExtensionPanel-B2sWNKxh.js (new) 9.51 kB 🔴 +9.51 kB 🔴 +2.69 kB 🔴 +2.39 kB
assets/ExtensionPanel-D7uIubJi.js (removed) 9.51 kB 🟢 -9.51 kB 🟢 -2.69 kB 🟢 -2.41 kB
assets/AboutPanel-Bvcgi-oc.js (new) 8.62 kB 🔴 +8.62 kB 🔴 +2.45 kB 🔴 +2.22 kB
assets/AboutPanel-DgZ4wf2m.js (removed) 8.62 kB 🟢 -8.62 kB 🟢 -2.45 kB 🟢 -2.21 kB
assets/ServerConfigPanel-CTb0ebbh.js (removed) 6.65 kB 🟢 -6.65 kB 🟢 -2.16 kB 🟢 -1.98 kB
assets/ServerConfigPanel-D0o7X97C.js (new) 6.65 kB 🔴 +6.65 kB 🔴 +2.17 kB 🔴 +1.96 kB
assets/UserPanel-Dkhrl4A5.js (new) 6.29 kB 🔴 +6.29 kB 🔴 +2.04 kB 🔴 +1.78 kB
assets/UserPanel-DrAxb5xz.js (removed) 6.29 kB 🟢 -6.29 kB 🟢 -2.03 kB 🟢 -1.78 kB
assets/cloudRemoteConfig-DhmVxEGo.js (removed) 1.45 kB 🟢 -1.45 kB 🟢 -718 B 🟢 -622 B
assets/cloudRemoteConfig-hGhAwC4-.js (new) 1.45 kB 🔴 +1.45 kB 🔴 +717 B 🔴 +625 B
assets/refreshRemoteConfig-C5nD9KV9.js (new) 1.14 kB 🔴 +1.14 kB 🔴 +522 B 🔴 +476 B
assets/refreshRemoteConfig-ELoj1AEx.js (removed) 1.14 kB 🟢 -1.14 kB 🟢 -519 B 🟢 -454 B
assets/config-B7YkIQwB.js 1.01 kB 1.01 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/settings-B9-DRLUq.js 33.3 kB 33.3 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/settings-BBhF1Ra7.js 23.9 kB 23.9 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/settings-BPmk7MJq.js 28 kB 28 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/settings-C6ThYRJH.js 27.1 kB 27.1 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/settings-CDls4Tnk.js 29.2 kB 29.2 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/settings-CXVW-KKN.js 27.3 kB 27.3 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/settings-CZBqKC2c.js 28.1 kB 28.1 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/settings-CzQJLe5j.js 29.8 kB 29.8 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/settings-IyjFFWib.js 31.6 kB 31.6 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/settings-LLMHzl4C.js 37.6 kB 37.6 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/settings-XT2QcP7J.js 23.3 kB 23.3 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B

Status: 11 added / 11 removed

User & Accounts — 16 kB (baseline 16 kB) • ⚪ 0 B

Authentication, profile, and account management bundles

File Before After Δ Raw Δ Gzip Δ Brotli
assets/auth-DpLlFg3K.js (new) 3.4 kB 🔴 +3.4 kB 🔴 +1.18 kB 🔴 +996 B
assets/auth-lR-Nj8kV.js (removed) 3.4 kB 🟢 -3.4 kB 🟢 -1.18 kB 🟢 -990 B
assets/SignUpForm-1Rh2vvPr.js (removed) 3.01 kB 🟢 -3.01 kB 🟢 -1.23 kB 🟢 -1.09 kB
assets/SignUpForm-DviZsLEs.js (new) 3.01 kB 🔴 +3.01 kB 🔴 +1.23 kB 🔴 +1.09 kB
assets/UpdatePasswordContent-D9p7XDGS.js (removed) 2.38 kB 🟢 -2.38 kB 🟢 -1.08 kB 🟢 -954 B
assets/UpdatePasswordContent-MIJQz09C.js (new) 2.38 kB 🔴 +2.38 kB 🔴 +1.08 kB 🔴 +950 B
assets/firebaseAuthStore-C6cunUM_.js (removed) 803 B 🟢 -803 B 🟢 -400 B 🟢 -357 B
assets/firebaseAuthStore-Ca71ZuxM.js (new) 803 B 🔴 +803 B 🔴 +398 B 🔴 +350 B
assets/auth-CIRznYjX.js (removed) 317 B 🟢 -317 B 🟢 -203 B 🟢 -178 B
assets/auth-YqCNqg0O.js (new) 317 B 🔴 +317 B 🔴 +206 B 🔴 +176 B
assets/PasswordFields-KhNVfxGF.js 4.51 kB 4.51 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/WorkspaceProfilePic-Dzy0Q-Jz.js 1.57 kB 1.57 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B

Status: 5 added / 5 removed

Editors & Dialogs — 751 B (baseline 751 B) • ⚪ 0 B

Modals, dialogs, drawers, and in-app editors

File Before After Δ Raw Δ Gzip Δ Brotli
assets/useSubscriptionDialog-5kLJsFDY.js (new) 751 B 🔴 +751 B 🔴 +391 B 🔴 +335 B
assets/useSubscriptionDialog-BCwuDCli.js (removed) 751 B 🟢 -751 B 🟢 -390 B 🟢 -337 B

Status: 1 added / 1 removed

UI Components — 36.6 kB (baseline 36.6 kB) • ⚪ 0 B

Reusable component library chunks

File Before After Δ Raw Δ Gzip Δ Brotli
assets/useTerminalTabs-BF8_1Gpg.js (removed) 9.86 kB 🟢 -9.86 kB 🟢 -3.41 kB 🟢 -3 kB
assets/useTerminalTabs-CgE9Y0Uh.js (new) 9.86 kB 🔴 +9.86 kB 🔴 +3.41 kB 🔴 +3 kB
assets/TopbarBadge-Crb5ki9L.js (new) 7.52 kB 🔴 +7.52 kB 🔴 +1.82 kB 🔴 +1.6 kB
assets/TopbarBadge-WqzfpwB2.js (removed) 7.52 kB 🟢 -7.52 kB 🟢 -1.82 kB 🟢 -1.61 kB
assets/ComfyQueueButton-CMZWn0tw.js (new) 7.17 kB 🔴 +7.17 kB 🔴 +2.32 kB 🔴 +2.08 kB
assets/ComfyQueueButton-DfqbuOzn.js (removed) 7.17 kB 🟢 -7.17 kB 🟢 -2.32 kB 🟢 -2.07 kB
assets/Button-Bdam854t.js (new) 3 kB 🔴 +3 kB 🔴 +1.21 kB 🔴 +1.06 kB
assets/Button-D-JRKour.js (removed) 3 kB 🟢 -3 kB 🟢 -1.21 kB 🟢 -1.06 kB
assets/SubscribeButton-C8tuXwta.js (removed) 2.35 kB 🟢 -2.35 kB 🟢 -1.02 kB 🟢 -884 B
assets/SubscribeButton-uZZIELCC.js (new) 2.35 kB 🔴 +2.35 kB 🔴 +1.02 kB 🔴 +890 B
assets/WidgetButton-4mWh4Pjc.js (removed) 1.84 kB 🟢 -1.84 kB 🟢 -877 B 🟢 -770 B
assets/WidgetButton-C2KeqJuI.js (new) 1.84 kB 🔴 +1.84 kB 🔴 +877 B 🔴 +771 B
assets/cloudFeedbackTopbarButton-BFTF2tOs.js (removed) 1.61 kB 🟢 -1.61 kB 🟢 -868 B 🟢 -773 B
assets/cloudFeedbackTopbarButton-uCuNXadC.js (new) 1.61 kB 🔴 +1.61 kB 🔴 +867 B 🔴 +768 B
assets/CloudBadge-CoT26Gzo.js (new) 1.24 kB 🔴 +1.24 kB 🔴 +607 B 🔴 +525 B
assets/CloudBadge-pw0WcXyY.js (removed) 1.24 kB 🟢 -1.24 kB 🟢 -609 B 🟢 -523 B
assets/ComfyQueueButton-C1_8XhSr.js (removed) 808 B 🟢 -808 B 🟢 -404 B 🟢 -359 B
assets/ComfyQueueButton-CbJD9qwh.js (new) 808 B 🔴 +808 B 🔴 +405 B 🔴 +362 B
assets/UserAvatar-C0eF2MUp.js 1.17 kB 1.17 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B

Status: 9 added / 9 removed

Data & Services — 2.11 MB (baseline 2.13 MB) • 🟢 -15.1 kB

Stores, services, APIs, and repositories

File Before After Δ Raw Δ Gzip Δ Brotli
assets/dialogService-DWitxf4c.js (removed) 1.35 MB 🟢 -1.35 MB 🟢 -304 kB 🟢 -235 kB
assets/dialogService-OLrGEwtb.js (new) 1.33 MB 🔴 +1.33 MB 🔴 +300 kB 🔴 +232 kB
assets/api-CxEyLoCT.js (new) 647 kB 🔴 +647 kB 🔴 +146 kB 🔴 +117 kB
assets/api-D3XjGmlV.js (removed) 647 kB 🟢 -647 kB 🟢 -146 kB 🟢 -117 kB
assets/load3dService-CnLPqfRU.js (new) 91.2 kB 🔴 +91.2 kB 🔴 +19.1 kB 🔴 +16.4 kB
assets/load3dService-D9aXZ8lj.js (removed) 91.2 kB 🟢 -91.2 kB 🟢 -19.1 kB 🟢 -16.5 kB
assets/systemStatsStore-CLKzAy4T.js (new) 12.2 kB 🔴 +12.2 kB 🔴 +4.27 kB 🔴 +3.74 kB
assets/systemStatsStore-CWOH4Jle.js (removed) 12.2 kB 🟢 -12.2 kB 🟢 -4.27 kB 🟢 -3.75 kB
assets/releaseStore-BLvMNbSu.js (removed) 7.99 kB 🟢 -7.99 kB 🟢 -2.23 kB 🟢 -1.96 kB
assets/releaseStore-M9Ik01Wp.js (new) 7.99 kB 🔴 +7.99 kB 🔴 +2.23 kB 🔴 +1.96 kB
assets/keybindingService-B1mL1TMi.js (removed) 6.57 kB 🟢 -6.57 kB 🟢 -1.72 kB 🟢 -1.49 kB
assets/keybindingService-BAgganTB.js (new) 6.57 kB 🔴 +6.57 kB 🔴 +1.72 kB 🔴 +1.48 kB
assets/dialogStore-q7bkx30L.js (removed) 4.1 kB 🟢 -4.1 kB 🟢 -1.24 kB 🟢 -1.1 kB
assets/dialogStore-wW2kWUZo.js (new) 4.1 kB 🔴 +4.1 kB 🔴 +1.24 kB 🔴 +1.09 kB
assets/bootstrapStore-C2KoH5Ch.js (removed) 2.13 kB 🟢 -2.13 kB 🟢 -883 B 🟢 -811 B
assets/bootstrapStore-Oy6aFaMg.js (new) 2.13 kB 🔴 +2.13 kB 🔴 +883 B 🔴 +807 B
assets/userStore-DrKYAsQu.js (new) 1.85 kB 🔴 +1.85 kB 🔴 +719 B 🔴 +628 B
assets/userStore-jXGqDgyu.js (removed) 1.85 kB 🟢 -1.85 kB 🟢 -718 B 🟢 -634 B
assets/audioService-B0H25sCF.js (removed) 1.73 kB 🟢 -1.73 kB 🟢 -848 B 🟢 -724 B
assets/audioService-LooFf9Cz.js (new) 1.73 kB 🔴 +1.73 kB 🔴 +844 B 🔴 +723 B
assets/releaseStore-BN8nDs0c.js (new) 775 B 🔴 +775 B 🔴 +395 B 🔴 +345 B
assets/releaseStore-DmQZeBJz.js (removed) 775 B 🟢 -775 B 🟢 -397 B 🟢 -346 B
assets/workflowDraftStore-DDWPUIoP.js (removed) 751 B 🟢 -751 B 🟢 -390 B 🟢 -342 B
assets/workflowDraftStore-TmyyWipm.js (new) 751 B 🔴 +751 B 🔴 +387 B 🔴 +340 B
assets/dialogService-B6Ex0WMp.js (new) 740 B 🔴 +740 B 🔴 +380 B 🔴 +335 B
assets/dialogService-BQTk4tHD.js (removed) 740 B 🟢 -740 B 🟢 -382 B 🟢 -338 B
assets/serverConfigStore-CG8z6LWz.js 2.32 kB 2.32 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B

Status: 13 added / 13 removed

Utilities & Hooks — 237 kB (baseline 237 kB) • ⚪ 0 B

Helpers, composables, and utility bundles

File Before After Δ Raw Δ Gzip Δ Brotli
assets/useConflictDetection-DbOZcvwP.js (new) 178 kB 🔴 +178 kB 🔴 +39.5 kB 🔴 +32.8 kB
assets/useConflictDetection-1x1RGKug.js (removed) 178 kB 🟢 -178 kB 🟢 -39.5 kB 🟢 -32.8 kB
assets/useLoad3d-CyXUSPf7.js (new) 14.7 kB 🔴 +14.7 kB 🔴 +3.64 kB 🔴 +3.21 kB
assets/useLoad3d-vjtw6NWs.js (removed) 14.7 kB 🟢 -14.7 kB 🟢 -3.63 kB 🟢 -3.21 kB
assets/useLoad3dViewer-BhtMLQTb.js (new) 14.2 kB 🔴 +14.2 kB 🔴 +3.15 kB 🔴 +2.8 kB
assets/useLoad3dViewer-lOYp8hS_.js (removed) 14.2 kB 🟢 -14.2 kB 🟢 -3.15 kB 🟢 -2.8 kB
assets/colorUtil-BRIBx2PN.js (removed) 7 kB 🟢 -7 kB 🟢 -2.14 kB 🟢 -1.89 kB
assets/colorUtil-D05wMZ2w.js (new) 7 kB 🔴 +7 kB 🔴 +2.14 kB 🔴 +1.91 kB
assets/useFeatureFlags-rF5wc2YW.js (removed) 3.34 kB 🟢 -3.34 kB 🟢 -1.05 kB 🟢 -901 B
assets/useFeatureFlags-TEZKNZBX.js (new) 3.34 kB 🔴 +3.34 kB 🔴 +1.04 kB 🔴 +905 B
assets/useWorkspaceUI-BlqsT0Yi.js (new) 3.15 kB 🔴 +3.15 kB 🔴 +889 B 🔴 +767 B
assets/useWorkspaceUI-LlXg2ViN.js (removed) 3.15 kB 🟢 -3.15 kB 🟢 -888 B 🟢 -766 B
assets/useSubscriptionCredits-TyHvmBR6.js (removed) 2.75 kB 🟢 -2.75 kB 🟢 -1.04 kB 🟢 -905 B
assets/useSubscriptionCredits-h8g6N6H8.js (new) 2.75 kB 🔴 +2.75 kB 🔴 +1.04 kB 🔴 +901 B
assets/subscriptionCheckoutUtil-D_9o3ChG.js (new) 2.53 kB 🔴 +2.53 kB 🔴 +1.06 kB 🔴 +951 B
assets/subscriptionCheckoutUtil-DQ0FqsxN.js (removed) 2.53 kB 🟢 -2.53 kB 🟢 -1.06 kB 🟢 -951 B
assets/useExternalLink---mz7cfR.js (new) 1.66 kB 🔴 +1.66 kB 🔴 +773 B 🔴 +685 B
assets/useExternalLink-CB3mj24K.js (removed) 1.66 kB 🟢 -1.66 kB 🟢 -773 B 🟢 -679 B
assets/useCopyToClipboard-CcV_w8Jd.js (removed) 1.57 kB 🟢 -1.57 kB 🟢 -665 B 🟢 -542 B
assets/useCopyToClipboard-CfvxnZiz.js (new) 1.57 kB 🔴 +1.57 kB 🔴 +667 B 🔴 +562 B
assets/useErrorHandling-DVAHeLjZ.js (new) 1.34 kB 🔴 +1.34 kB 🔴 +554 B 🔴 +513 B
assets/useErrorHandling-hg5Dgjz7.js (removed) 1.34 kB 🟢 -1.34 kB 🟢 -552 B 🟢 -478 B
assets/useLoad3d-B0Z7Yw8x.js (removed) 874 B 🟢 -874 B 🟢 -438 B 🟢 -389 B
assets/useLoad3d-CueeokrU.js (new) 874 B 🔴 +874 B 🔴 +436 B 🔴 +388 B
assets/audioUtils-2J5ajAsZ.js (removed) 858 B 🟢 -858 B 🟢 -500 B 🟢 -421 B
assets/audioUtils-DqeQnLTq.js (new) 858 B 🔴 +858 B 🔴 +499 B 🔴 +419 B
assets/useLoad3dViewer-BpxAGgra.js (removed) 853 B 🟢 -853 B 🟢 -424 B 🟢 -377 B
assets/useLoad3dViewer-CCyYWC7L.js (new) 853 B 🔴 +853 B 🔴 +421 B 🔴 +379 B
assets/useCurrentUser-BloTG2CD.js (new) 737 B 🔴 +737 B 🔴 +386 B 🔴 +336 B
assets/useCurrentUser-BqX5gKRQ.js (removed) 737 B 🟢 -737 B 🟢 -386 B 🟢 -337 B
assets/_plugin-vue_export-helper-D53b894U.js 315 B 315 B ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/envUtil-BoEUYO9X.js 466 B 466 B ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/markdownRendererUtil-YzPqYQr3.js 1.56 kB 1.56 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/networkUtil-DSA9UCpE.js 1.07 kB 1.07 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/SkeletonUtils-CWsb-x0f.js 133 B 133 B ⚪ 0 B ⚪ 0 B ⚪ 0 B

Status: 15 added / 15 removed

Vendor & Third-Party — 8.77 MB (baseline 8.77 MB) • 🔴 +14 B

External libraries and shared vendor chunks

File Before After Δ Raw Δ Gzip Δ Brotli
assets/vendor-other-BBfV138E.js (new) 1.55 MB 🔴 +1.55 MB 🔴 +323 kB 🔴 +257 kB
assets/vendor-other-BjIHN7VK.js (removed) 1.55 MB 🟢 -1.55 MB 🟢 -323 kB 🟢 -257 kB
assets/vendor-axios-qYA_aG5-.js 71.6 kB 71.6 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/vendor-chart-DPuwexxf.js 399 kB 399 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/vendor-firebase-CLEC0CcJ.js 842 kB 842 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/vendor-i18n-Djj6y3EO.js 132 kB 132 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/vendor-markdown-CLFqBOQ2.js 102 kB 102 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/vendor-primevue-DaJr0o4X.js 1.74 MB 1.74 MB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/vendor-reka-ui-BfJUTI-3.js 240 kB 240 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/vendor-sentry-BVA5kbUC.js 183 kB 183 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/vendor-three-Q97wQk05.js 1.8 MB 1.8 MB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/vendor-tiptap-eGUDVAYp.js 632 kB 632 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/vendor-vue-core-DnRx4pHA.js 312 kB 312 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/vendor-vueuse-CfaD9iqz.js 111 kB 111 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/vendor-xterm-0CcpQUK2.js 398 kB 398 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/vendor-yjs-B7dXz571.js 143 kB 143 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/vendor-zod-BTzCBa7h.js 110 kB 110 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B

Status: 1 added / 1 removed

Other — 7.29 MB (baseline 7.29 MB) • 🔴 +36 B

Bundles that do not match a named category

File Before After Δ Raw Δ Gzip Δ Brotli
assets/i18n-D5MIIM9k.js (new) 492 kB 🔴 +492 kB 🔴 +94.2 kB 🔴 +73.4 kB
assets/i18n-o9Atcop2.js (removed) 492 kB 🟢 -492 kB 🟢 -94.2 kB 🟢 -73.4 kB
assets/core-BONE9wQj.js (removed) 72.4 kB 🟢 -72.4 kB 🟢 -18.7 kB 🟢 -16 kB
assets/core-CWQ5Kam3.js (new) 72.4 kB 🔴 +72.4 kB 🔴 +18.7 kB 🔴 +16 kB
assets/groupNode-BVtcP3aD.js (removed) 72.2 kB 🟢 -72.2 kB 🟢 -17.8 kB 🟢 -15.7 kB
assets/groupNode-jvmgkXM-.js (new) 72.2 kB 🔴 +72.2 kB 🔴 +17.8 kB 🔴 +15.7 kB
assets/WidgetSelect-CJ2V3Z-r.js (new) 57.6 kB 🔴 +57.6 kB 🔴 +12.2 kB 🔴 +10.6 kB
assets/WidgetSelect-S9fvixFk.js (removed) 57.6 kB 🟢 -57.6 kB 🟢 -12.2 kB 🟢 -10.6 kB
assets/SubscriptionRequiredDialogContentWorkspace-Bn0EICeG.js (removed) 46 kB 🟢 -46 kB 🟢 -8.59 kB 🟢 -7.43 kB
assets/SubscriptionRequiredDialogContentWorkspace-CzxliF4K.js (new) 46 kB 🔴 +46 kB 🔴 +8.6 kB 🔴 +7.47 kB
assets/SettingDialogContent-BhUu-vFG.js (removed) 31.9 kB 🟢 -31.9 kB 🟢 -8.33 kB 🟢 -7.33 kB
assets/SettingDialogContent-BvYAvaCF.js (new) 31.9 kB 🔴 +31.9 kB 🔴 +8.34 kB 🔴 +7.32 kB
assets/Load3DControls-BgXLqj5P.js (new) 30.9 kB 🔴 +30.9 kB 🔴 +5.34 kB 🔴 +4.64 kB
assets/Load3DControls-CrDL_auP.js (removed) 30.9 kB 🟢 -30.9 kB 🟢 -5.34 kB 🟢 -4.64 kB
assets/SubscriptionRequiredDialogContent-C3BULm5h.js (removed) 26.2 kB 🟢 -26.2 kB 🟢 -6.59 kB 🟢 -5.79 kB
assets/SubscriptionRequiredDialogContent-DAPLSF1U.js (new) 26.2 kB 🔴 +26.2 kB 🔴 +6.58 kB 🔴 +5.79 kB
assets/Load3dViewerContent-BFA2FKV9.js (new) 23.1 kB 🔴 +23.1 kB 🔴 +5.2 kB 🔴 +4.51 kB
assets/Load3dViewerContent-ThUPQFvc.js (removed) 23.1 kB 🟢 -23.1 kB 🟢 -5.2 kB 🟢 -4.51 kB
assets/WidgetImageCrop-B2I53BMJ.js (removed) 22.3 kB 🟢 -22.3 kB 🟢 -5.52 kB 🟢 -4.85 kB
assets/WidgetImageCrop-zUKDYdD_.js (new) 22.3 kB 🔴 +22.3 kB 🔴 +5.52 kB 🔴 +4.86 kB
assets/SubscriptionPanelContentWorkspace-BtpIQYJ8.js (removed) 21.8 kB 🟢 -21.8 kB 🟢 -5.18 kB 🟢 -4.58 kB
assets/SubscriptionPanelContentWorkspace-Dcu1Z-Y_.js (new) 21.8 kB 🔴 +21.8 kB 🔴 +5.18 kB 🔴 +4.58 kB
assets/CurrentUserPopoverWorkspace-DpcIFZ8f.js (removed) 20.6 kB 🟢 -20.6 kB 🟢 -5.08 kB 🟢 -4.51 kB
assets/CurrentUserPopoverWorkspace-FC4EOScP.js (new) 20.6 kB 🔴 +20.6 kB 🔴 +5.08 kB 🔴 +4.51 kB
assets/FormItem-BasLUoDz.js (new) 20.2 kB 🔴 +20.2 kB 🔴 +4.86 kB 🔴 +4.25 kB
assets/FormItem-DkSy74EH.js (removed) 20.2 kB 🟢 -20.2 kB 🟢 -4.86 kB 🟢 -4.25 kB
assets/SignInContent-2-5RZ263.js (new) 19 kB 🔴 +19 kB 🔴 +4.82 kB 🔴 +4.22 kB
assets/SignInContent-ASj40qww.js (removed) 19 kB 🟢 -19 kB 🟢 -4.82 kB 🟢 -4.21 kB
assets/WidgetRecordAudio-D3B0LnlD.js (new) 17.3 kB 🔴 +17.3 kB 🔴 +4.96 kB 🔴 +4.43 kB
assets/WidgetRecordAudio-eq7I9X7E.js (removed) 17.3 kB 🟢 -17.3 kB 🟢 -4.96 kB 🟢 -4.43 kB
assets/MissingModelsWarning-DliIqu7u.js (removed) 17.2 kB 🟢 -17.2 kB 🟢 -4.7 kB 🟢 -4.17 kB
assets/MissingModelsWarning-DPVCYB3Y.js (new) 17.2 kB 🔴 +17.2 kB 🔴 +4.71 kB 🔴 +4.18 kB
assets/Load3D-C6CDhYWY.js (new) 16.2 kB 🔴 +16.2 kB 🔴 +4.04 kB 🔴 +3.53 kB
assets/Load3D-sx66pZfw.js (removed) 16.2 kB 🟢 -16.2 kB 🟢 -4.04 kB 🟢 -3.53 kB
assets/WidgetInputNumber-C26xeaUo.js (new) 15.8 kB 🔴 +15.8 kB 🔴 +4.26 kB 🔴 +3.79 kB
assets/WidgetInputNumber-DuGDC5n0.js (removed) 15.8 kB 🟢 -15.8 kB 🟢 -4.26 kB 🟢 -3.8 kB
assets/load3d-BdqOve7M.js (removed) 14.8 kB 🟢 -14.8 kB 🟢 -4.2 kB 🟢 -3.65 kB
assets/load3d-BndSpNxK.js (new) 14.8 kB 🔴 +14.8 kB 🔴 +4.21 kB 🔴 +3.64 kB
assets/LazyImage-9f6CAdqs.js (removed) 12.3 kB 🟢 -12.3 kB 🟢 -3.79 kB 🟢 -3.33 kB
assets/LazyImage-DGzPrS2Y.js (new) 12.3 kB 🔴 +12.3 kB 🔴 +3.79 kB 🔴 +3.35 kB
assets/AudioPreviewPlayer-3-KTk010.js (removed) 10.9 kB 🟢 -10.9 kB 🟢 -3.21 kB 🟢 -2.86 kB
assets/AudioPreviewPlayer-Drtw72Qk.js (new) 10.9 kB 🔴 +10.9 kB 🔴 +3.21 kB 🔴 +2.86 kB
assets/NodeConflictDialogContent-Cs9fCFpH.js (new) 10.5 kB 🔴 +10.5 kB 🔴 +2.36 kB 🔴 +2.08 kB
assets/NodeConflictDialogContent-DfA86N5L.js (removed) 10.5 kB 🟢 -10.5 kB 🟢 -2.35 kB 🟢 -2.06 kB
assets/changeTracker-TUJN8mVP.js (new) 9.4 kB 🔴 +9.4 kB 🔴 +2.9 kB 🔴 +2.56 kB
assets/changeTracker-xZw0ly6_.js (removed) 9.4 kB 🟢 -9.4 kB 🟢 -2.9 kB 🟢 -2.56 kB
assets/nodeTemplates-C2n_oZDf.js (new) 9.34 kB 🔴 +9.34 kB 🔴 +3.28 kB 🔴 +2.88 kB
assets/nodeTemplates-DmFwIai_.js (removed) 9.34 kB 🟢 -9.34 kB 🟢 -3.28 kB 🟢 -2.88 kB
assets/SelectValue-BBe0nxmR.js (new) 8.94 kB 🔴 +8.94 kB 🔴 +2.26 kB 🔴 +1.99 kB
assets/SelectValue-Cd45aXPi.js (removed) 8.94 kB 🟢 -8.94 kB 🟢 -2.27 kB 🟢 -1.99 kB
assets/InviteMemberDialogContent-ABZ0Hzoz.js (new) 7.92 kB 🔴 +7.92 kB 🔴 +2.56 kB 🔴 +2.23 kB
assets/InviteMemberDialogContent-Dp_7B1FD.js (removed) 7.92 kB 🟢 -7.92 kB 🟢 -2.56 kB 🟢 -2.25 kB
assets/WidgetWithControl-CiR60R_b.js (new) 7.04 kB 🔴 +7.04 kB 🔴 +2.63 kB 🔴 +2.35 kB
assets/WidgetWithControl-P96lRq9Z.js (removed) 7.04 kB 🟢 -7.04 kB 🟢 -2.64 kB 🟢 -2.36 kB
assets/MissingNodesFooter-C7GRND7n.js (removed) 6.73 kB 🟢 -6.73 kB 🟢 -2.29 kB 🟢 -2.06 kB
assets/MissingNodesFooter-MTT584dP.js (new) 6.73 kB 🔴 +6.73 kB 🔴 +2.29 kB 🔴 +2.05 kB
assets/Load3DConfiguration-DAcQqm3X.js (removed) 6.36 kB 🟢 -6.36 kB 🟢 -1.92 kB 🟢 -1.69 kB
assets/Load3DConfiguration-e77IkAIU.js (new) 6.36 kB 🔴 +6.36 kB 🔴 +1.93 kB 🔴 +1.69 kB
assets/MissingNodesContent-C_uKTxui.js (removed) 6.15 kB 🟢 -6.15 kB 🟢 -2.09 kB 🟢 -1.85 kB
assets/MissingNodesContent-CQxIbM3c.js (new) 6.15 kB 🔴 +6.15 kB 🔴 +2.09 kB 🔴 +1.85 kB
assets/CreateWorkspaceDialogContent-Ba_gt_m4.js (new) 5.55 kB 🔴 +5.55 kB 🔴 +2 kB 🔴 +1.74 kB
assets/CreateWorkspaceDialogContent-DYQ3b4kF.js (removed) 5.55 kB 🟢 -5.55 kB 🟢 -2 kB 🟢 -1.75 kB
assets/EditWorkspaceDialogContent-cMkrtoEs.js (new) 5.35 kB 🔴 +5.35 kB 🔴 +1.96 kB 🔴 +1.71 kB
assets/EditWorkspaceDialogContent-DPV85CFk.js (removed) 5.35 kB 🟢 -5.35 kB 🟢 -1.96 kB 🟢 -1.71 kB
assets/ValueControlPopover-BqRYIoIl.js (removed) 4.93 kB 🟢 -4.93 kB 🟢 -1.78 kB 🟢 -1.59 kB
assets/ValueControlPopover-jno2JfRs.js (new) 4.93 kB 🔴 +4.93 kB 🔴 +1.78 kB 🔴 +1.59 kB
assets/Preview3d-BcBGOXWh.js (new) 4.83 kB 🔴 +4.83 kB 🔴 +1.58 kB 🔴 +1.37 kB
assets/Preview3d-C56Osrj7.js (removed) 4.83 kB 🟢 -4.83 kB 🟢 -1.58 kB 🟢 -1.38 kB
assets/CancelSubscriptionDialogContent-CkLZH4rv.js (removed) 4.81 kB 🟢 -4.81 kB 🟢 -1.79 kB 🟢 -1.57 kB
assets/CancelSubscriptionDialogContent-DwyXPxRK.js (new) 4.81 kB 🔴 +4.81 kB 🔴 +1.79 kB 🔴 +1.57 kB
assets/AnimationControls-B7792UyM.js (removed) 4.61 kB 🟢 -4.61 kB 🟢 -1.6 kB 🟢 -1.41 kB
assets/AnimationControls-BUivU30B.js (new) 4.61 kB 🔴 +4.61 kB 🔴 +1.6 kB 🔴 +1.41 kB
assets/DeleteWorkspaceDialogContent-C7MG-aX1.js (removed) 4.25 kB 🟢 -4.25 kB 🟢 -1.64 kB 🟢 -1.43 kB
assets/DeleteWorkspaceDialogContent-CloTRSqZ.js (new) 4.25 kB 🔴 +4.25 kB 🔴 +1.64 kB 🔴 +1.43 kB
assets/LeaveWorkspaceDialogContent-DKPkVmay.js (new) 4.08 kB 🔴 +4.08 kB 🔴 +1.59 kB 🔴 +1.38 kB
assets/LeaveWorkspaceDialogContent-DvMe4byg.js (removed) 4.08 kB 🟢 -4.08 kB 🟢 -1.59 kB 🟢 -1.38 kB
assets/RemoveMemberDialogContent-BkfV2wcE.js (removed) 4.06 kB 🟢 -4.06 kB 🟢 -1.54 kB 🟢 -1.34 kB
assets/RemoveMemberDialogContent-BL9INgOE.js (new) 4.06 kB 🔴 +4.06 kB 🔴 +1.54 kB 🔴 +1.34 kB
assets/RevokeInviteDialogContent-CmBC5_Vl.js (new) 3.98 kB 🔴 +3.98 kB 🔴 +1.56 kB 🔴 +1.36 kB
assets/RevokeInviteDialogContent-DqYUkB-u.js (removed) 3.98 kB 🟢 -3.98 kB 🟢 -1.55 kB 🟢 -1.37 kB
assets/Slider-BpDHOFfi.js (removed) 3.52 kB 🟢 -3.52 kB 🟢 -1.36 kB 🟢 -1.19 kB
assets/Slider-ItMZ_VJm.js (new) 3.52 kB 🔴 +3.52 kB 🔴 +1.36 kB 🔴 +1.19 kB
assets/saveMesh-BloTqDP9.js (new) 3.43 kB 🔴 +3.43 kB 🔴 +1.47 kB 🔴 +1.31 kB
assets/saveMesh-Dz-RIKh4.js (removed) 3.43 kB 🟢 -3.43 kB 🟢 -1.48 kB 🟢 -1.31 kB
assets/WidgetTextarea-DGoaM4W-.js (new) 3.14 kB 🔴 +3.14 kB 🔴 +1.3 kB 🔴 +1.14 kB
assets/WidgetTextarea-DKZNqX1s.js (removed) 3.14 kB 🟢 -3.14 kB 🟢 -1.3 kB 🟢 -1.14 kB
assets/cloudSessionCookie-7V8S6H4C.js (new) 3.12 kB 🔴 +3.12 kB 🔴 +1.1 kB 🔴 +992 B
assets/cloudSessionCookie-BStMw1gj.js (removed) 3.12 kB 🟢 -3.12 kB 🟢 -1.09 kB 🟢 -963 B
assets/GlobalToast-AukMITan.js (new) 2.91 kB 🔴 +2.91 kB 🔴 +1.21 kB 🔴 +1.06 kB
assets/GlobalToast-SLIrXChn.js (removed) 2.91 kB 🟢 -2.91 kB 🟢 -1.21 kB 🟢 -1.03 kB
assets/WidgetColorPicker-DFKj0CIe.js (removed) 2.9 kB 🟢 -2.9 kB 🟢 -1.23 kB 🟢 -1.11 kB
assets/WidgetColorPicker-kD53kaGg.js (new) 2.9 kB 🔴 +2.9 kB 🔴 +1.23 kB 🔴 +1.11 kB
assets/ApiNodesSignInContent-CkB682yp.js (new) 2.69 kB 🔴 +2.69 kB 🔴 +1.05 kB 🔴 +965 B
assets/ApiNodesSignInContent-sS4I7UMQ.js (removed) 2.69 kB 🟢 -2.69 kB 🟢 -1.05 kB 🟢 -921 B
assets/WidgetToggleSwitch-DyUmrxBZ.js (removed) 2.5 kB 🟢 -2.5 kB 🟢 -1.09 kB 🟢 -971 B
assets/WidgetToggleSwitch-UGh0LXy0.js (new) 2.5 kB 🔴 +2.5 kB 🔴 +1.09 kB 🔴 +968 B
assets/NodeConflictFooter-_SUYUK_E.js (removed) 2.37 kB 🟢 -2.37 kB 🟢 -1.03 kB 🟢 -912 B
assets/NodeConflictFooter-8jjbJGIp.js (new) 2.37 kB 🔴 +2.37 kB 🔴 +1.03 kB 🔴 +911 B
assets/SubscribeToRun-C0diMRhO.js (new) 2.2 kB 🔴 +2.2 kB 🔴 +1.01 kB 🔴 +891 B
assets/SubscribeToRun-DfP1pE9o.js (removed) 2.2 kB 🟢 -2.2 kB 🟢 -1.01 kB 🟢 -869 B
assets/WidgetLayoutField-B5nsgfe8.js (removed) 1.95 kB 🟢 -1.95 kB 🟢 -874 B 🟢 -762 B
assets/WidgetLayoutField-sYCRn3lB.js (new) 1.95 kB 🔴 +1.95 kB 🔴 +875 B 🔴 +766 B
assets/ImportFailedNodeFooter-CQHihumr.js (removed) 1.88 kB 🟢 -1.88 kB 🟢 -865 B 🟢 -754 B
assets/ImportFailedNodeFooter-Dk2XlzXX.js (new) 1.88 kB 🔴 +1.88 kB 🔴 +866 B 🔴 +758 B
assets/WidgetInputText-C-uE2bRZ.js (new) 1.86 kB 🔴 +1.86 kB 🔴 +874 B 🔴 +793 B
assets/WidgetInputText-D-efAVZy.js (removed) 1.86 kB 🟢 -1.86 kB 🟢 -873 B 🟢 -799 B
assets/SettingDialogHeader-BEZySzOX.js (removed) 1.8 kB 🟢 -1.8 kB 🟢 -893 B 🟢 -807 B
assets/SettingDialogHeader-Cgnb-lVE.js (new) 1.8 kB 🔴 +1.8 kB 🔴 +893 B 🔴 +808 B
assets/CloudRunButtonWrapper-DS2MFh48.js (new) 1.69 kB 🔴 +1.69 kB 🔴 +800 B 🔴 +720 B
assets/CloudRunButtonWrapper-Dul3nH3r.js (removed) 1.69 kB 🟢 -1.69 kB 🟢 -794 B 🟢 -720 B
assets/signInSchema-CIbsZfnG.js (removed) 1.53 kB 🟢 -1.53 kB 🟢 -561 B 🟢 -510 B
assets/signInSchema-DvHFUfOz.js (new) 1.53 kB 🔴 +1.53 kB 🔴 +565 B 🔴 +520 B
assets/cloudBadges-B_Fgu8X5.js (removed) 1.38 kB 🟢 -1.38 kB 🟢 -718 B 🟢 -623 B
assets/cloudBadges-CKY6L-46.js (new) 1.38 kB 🔴 +1.38 kB 🔴 +721 B 🔴 +624 B
assets/cloudSubscription-D3cvJqZJ.js (new) 1.34 kB 🔴 +1.34 kB 🔴 +669 B 🔴 +577 B
assets/cloudSubscription-DUccjBaQ.js (removed) 1.34 kB 🟢 -1.34 kB 🟢 -667 B 🟢 -575 B
assets/Load3D-CxjoWhre.js (removed) 1.09 kB 🟢 -1.09 kB 🟢 -510 B 🟢 -451 B
assets/Load3D-r2muaSn6.js (new) 1.09 kB 🔴 +1.09 kB 🔴 +509 B 🔴 +453 B
assets/nightlyBadges-1ciiXt1q.js (new) 1.02 kB 🔴 +1.02 kB 🔴 +545 B 🔴 +483 B
assets/nightlyBadges-BwJTEbVF.js (removed) 1.02 kB 🟢 -1.02 kB 🟢 -547 B 🟢 -482 B
assets/Load3dViewerContent-7VrnxQMp.js (removed) 1.01 kB 🟢 -1.01 kB 🟢 -482 B 🟢 -426 B
assets/Load3dViewerContent-DePQSHi8.js (new) 1.01 kB 🔴 +1.01 kB 🔴 +481 B 🔴 +429 B
assets/SubscriptionPanelContentWorkspace-CQ2YC8fJ.js (new) 945 B 🔴 +945 B 🔴 +448 B 🔴 +391 B
assets/SubscriptionPanelContentWorkspace-DgyWkGe_.js (removed) 945 B 🟢 -945 B 🟢 -449 B 🟢 -389 B
assets/SettingDialogContent-BJn2dNfc.js (removed) 887 B 🟢 -887 B 🟢 -433 B 🟢 -378 B
assets/SettingDialogContent-CHAL1rX7.js (new) 887 B 🔴 +887 B 🔴 +432 B 🔴 +383 B
assets/changeTracker-g7v9CU2q.js (removed) 772 B 🟢 -772 B 🟢 -397 B 🟢 -346 B
assets/changeTracker-mhAK9kvM.js (new) 772 B 🔴 +772 B 🔴 +397 B 🔴 +341 B
assets/graphHasMissingNodes-8lA2xXJr.js (removed) 761 B 🟢 -761 B 🟢 -374 B 🟢 -322 B
assets/graphHasMissingNodes-prmvcJQj.js (new) 761 B 🔴 +761 B 🔴 +373 B 🔴 +323 B
assets/WidgetLegacy-BR9nf8pq.js (removed) 760 B 🟢 -760 B 🟢 -396 B 🟢 -344 B
assets/WidgetLegacy-DXZMcxmK.js (new) 760 B 🔴 +760 B 🔴 +398 B 🔴 +343 B
assets/WidgetInputNumber-BGlMS98f.js (removed) 392 B 🟢 -392 B 🟢 -233 B 🟢 -211 B
assets/WidgetInputNumber-CP6VkF2b.js (new) 392 B 🔴 +392 B 🔴 +230 B 🔴 +197 B
assets/SettingDialogHeader-BpIHBb3N.js (removed) 345 B 🟢 -345 B 🟢 -214 B 🟢 -208 B
assets/SettingDialogHeader-CCrmtDoS.js (new) 345 B 🔴 +345 B 🔴 +213 B 🔴 +200 B
assets/src-Bexa6sQp.js (new) 251 B 🔴 +251 B 🔴 +211 B 🔴 +183 B
assets/src-CWktmgrp.js (removed) 251 B 🟢 -251 B 🟢 -211 B 🟢 -185 B
assets/i18n-Cp91M_GM.js (removed) 199 B 🟢 -199 B 🟢 -160 B 🟢 -139 B
assets/i18n-DmUwX7L9.js (new) 199 B 🔴 +199 B 🔴 +160 B 🔴 +138 B
assets/auto-zCGpezkl.js 1.7 kB 1.7 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/BaseViewTemplate-XnByb1vt.js 1.78 kB 1.78 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/comfy-logo-single-CzGozBag.js 198 B 198 B ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/ComfyOrgHeader-DiJp3aEW.js 910 B 910 B ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/commands-BaWekgk-.js 14.7 kB 14.7 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/commands-BDDnqSnY.js 15.8 kB 15.8 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/commands-BoYLZfP6.js 15.7 kB 15.7 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/commands-BQBGh0Ya.js 15.5 kB 15.5 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/commands-BRoxhQgK.js 15.8 kB 15.8 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/commands-C_sqX4RY.js 14.9 kB 14.9 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/commands-Cd2uuEbd.js 17.1 kB 17.1 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/commands-CXPUqoOz.js 16.6 kB 16.6 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/commands-ijoJFfEv.js 16.3 kB 16.3 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/commands-UTYbUnOi.js 17.2 kB 17.2 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/commands-YFdvkJDc.js 18.4 kB 18.4 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/constants-BQ60oUwg.js 579 B 579 B ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/ImportFailedNodeContent-DLHL7-Dp.js 2.48 kB 2.48 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/ImportFailedNodeHeader-CBKT1iLw.js 1.08 kB 1.08 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/main-Bk7Ph3VS.js 140 kB 140 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/main-BsU_fTOy.js 118 kB 118 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/main-BYY1tCjz.js 153 kB 153 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/main-BzI-1UKY.js 117 kB 117 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/main-ciwZVtD5.js 133 kB 133 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/main-CjTKnSQT.js 135 kB 135 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/main-ClVfAHiD.js 185 kB 185 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/main-DtZZaQoT.js 137 kB 137 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/main-DY5snELF.js 160 kB 160 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/main-Q_yKaq1U.js 166 kB 166 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/main-XVEzvvBB.js 132 kB 132 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/Media3DTop-BRnZCRYc.js 1.82 kB 1.82 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/MediaAudioTop-o68UYik3.js 1.43 kB 1.43 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/MediaImageTop-C6_liv9g.js 1.75 kB 1.75 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/MediaVideoTop-BXztKli7.js 2.23 kB 2.23 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/MissingNodesHeader-DJHfQF1y.js 1.09 kB 1.09 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/NodeConflictHeader-DXOchtCS.js 1.09 kB 1.09 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/nodeDefs-BbE7kmki.js 413 kB 413 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/nodeDefs-C4Vr6-Ih.js 367 kB 367 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/nodeDefs-CeGNv9ZW.js 450 kB 450 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/nodeDefs-CgbjMWnR.js 360 kB 360 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/nodeDefs-Cj0eoGwS.js 371 kB 371 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/nodeDefs-CjZ27bLt.js 412 kB 412 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/nodeDefs-CPZbmaZd.js 367 kB 367 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/nodeDefs-Cz-81naW.js 335 kB 335 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/nodeDefs-DknKGYI5.js 364 kB 364 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/nodeDefs-elNKIbDk.js 381 kB 381 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/nodeDefs-VAK4vMLf.js 338 kB 338 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/OBJLoader2WorkerModule-DTMpvldF.js 109 kB 109 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/PanelTemplate-Co9CIrpq.js 1.2 kB 1.2 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/previousFullPath-D7OXsRO9.js 665 B 665 B ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/rolldown-runtime-Ca2S-reV.js 1.87 kB 1.87 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/telemetry-C9AnI0k5.js 226 B 226 B ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/types-BYdQ-wbS.js 245 B 245 B ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/widget-DZ2L2V2o.js 445 B 445 B ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/WidgetBoundingBox-C24zoQ9e.js 3.95 kB 3.95 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/WidgetBoundingBox-Dlh3X2pa.js 131 B 131 B ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/WidgetChart-Dz-i33ej.js 2.21 kB 2.21 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/WidgetGalleria-DLvy9VuC.js 3.61 kB 3.61 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/WidgetImageCompare-1sy6l8-0.js 3.1 kB 3.1 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/WidgetMarkdown-BP5qyCxZ.js 2.88 kB 2.88 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/widgetPropFilter-DyQHILEf.js 1.1 kB 1.1 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/widgetTypes-BRoEExOD.js 393 B 393 B ⚪ 0 B ⚪ 0 B ⚪ 0 B

Status: 70 added / 70 removed

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Fix all issues with AI agents
In `@src/components/rightSidePanel/RightSidePanel.vue`:
- Around line 104-110: The "Error" label is hardcoded in the list.push call
inside RightSidePanel.vue; replace the literal with the vue-i18n Composition API
call (use useI18n() / t) so the label returns the translated key g.error (i.e.,
obtain t from useI18n in the component setup and change label: () => 'Error' to
label: () => t('g.error')), ensuring selectedNodeErrors and the existing
list.push usage remain unchanged.

In `@src/renderer/extensions/vueNodes/components/NodeBadges.vue`:
- Around line 12-42: The explicit bg-color prop on NodeBadge is being overridden
by v-bind="badge" in both the core and extension badge loops; to fix, change the
prop order so the explicit bg-color="transparent" takes precedence (e.g., bind
badge first then set bg-color, or spread/merge badge with bgColor:
'transparent') for the NodeBadge usages inside the core and extension v-for
templates so badges remain transparent.
🧹 Nitpick comments (6)
src/components/rightSidePanel/TabError.vue (2)

4-4: Use $t in template instead of importing t.

Since t is only used within the template (line 14), prefer using the built-in $t in the template rather than importing from @/i18n. This avoids unnecessary imports when t is not used in the script.

♻️ Suggested refactor
-import { t } from '@/i18n'

And in the template:

-      {{ t('g.copy') }}
+      {{ $t('g.copy') }}

Based on learnings: "In Vue single-file components where the i18n t function is only used within the template, prefer using the built-in $t in the template instead of importing useI18n and destructuring t in the script."


11-25: Consider wrapping the template in a single root element.

The template has multiple root elements: a wrapper div for the button (lines 12-17) and multiple divs from the v-for loop (lines 18-25). While Vue 3 supports fragments, wrapping in a single container improves layout consistency and makes styling more predictable.

♻️ Suggested refactor
 <template>
+  <div class="flex flex-col">
     <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>
+  </div>
 </template>
src/components/rightSidePanel/RightSidePanel.vue (1)

95-100: Consider the FIXME for showing all errors when nothing is selected.

The FIXME comment raises a valid point about showing all errors when no nodes are selected. Currently, errors are only shown for selected nodes. Consider whether users would benefit from seeing all errors in the workflow overview.

Would you like me to help implement a solution that shows all workflow errors when nothing is selected, or would you prefer to track this as a separate issue?

src/renderer/extensions/vueNodes/components/NodeHeader.vue (1)

109-113: Consider extracting a shared PriceBadge type.
The { required: string; rest?: string } shape is now used in multiple places (e.g., this prop and the partitioning composable). A shared type keeps the contract aligned.

As per coding guidelines: Extract and name complex type definitions that are inlined in multiple related places for reuse.

src/renderer/extensions/vueNodes/components/LGraphNode.vue (2)

89-124: Avoid passing a pricing attr to NodeBadges via v-bind.
Overriding with :pricing="undefined" works, but it’s brittle. Consider binding only the props NodeBadges accepts.

♻️ Suggested refactor
 const { startDrag } = useNodeDrag()
 const badges = usePartitionedBadges(nodeData)
+const badgeGroups = computed(() => {
+  const { pricing, ...rest } = badges.value
+  return rest
+})
-        <NodeBadges v-bind="badges" :pricing="undefined" />
+        <NodeBadges v-bind="badgeGroups" />

126-164: Use shared button components for the bottom actions.
The raw <button> elements bypass the repo’s common button components, which can lead to inconsistent theming and behavior. Consider swapping each action to IconTextButton/TextButton (or similar) from src/components/button/ and moving the v-if/else chain onto those components.

Based on learnings: In Vue files across the ComfyUI_frontend repo, when a button is needed, prefer the repo's common button components from src/components/button/ (IconButton.vue, TextButton.vue, IconTextButton.vue) over plain HTML elements. These components wrap PrimeVue with the project’s design system styling. Use only the common button components for consistency and theming, and import them from src/components/button/ as needed.

@AustinMroz AustinMroz added the New Browser Test Expectations New browser test screenshot should be set by github action label Feb 4, 2026
@github-actions
Copy link

github-actions bot commented Feb 4, 2026

Updating Playwright Expectations

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/renderer/extensions/vueNodes/components/LGraphNode.subgraph.test.ts (1)

150-172: ⚠️ Potential issue | 🟡 Minor

Test targets dblclick but the component uses @click.stop.

The test triggers a dblclick event and claims to test the @dblclick.stop directive, but LGraphNode.vue (line 146) uses @click.stop. The assertion only checks that the button exists, which doesn't verify event propagation behavior. Consider either:

  1. Testing click instead of dblclick
  2. Actually verifying that propagation is stopped by checking a parent handler wasn't called
🧪 Suggested fix to test click propagation
   it('should prevent event propagation on double click', async () => {
+  it('should prevent event propagation on click', async () => {
     await setupMocks(true) // isSubgraph = true

     const wrapper = createWrapper({
       nodeData: createMockNodeData('test-node-1')
     })

     await wrapper.vm.$nextTick()

     const subgraphButton = wrapper.find('[data-testid="subgraph-enter-button"]')

-    // Mock event object
-    const mockEvent = {
-      stopPropagation: vi.fn()
-    }
-
-    // Trigger dblclick event
-    await subgraphButton.trigger('dblclick', mockEvent)
-
-    // Should prevent propagation (handled by `@dblclick.stop` directive)
-    // This is tested by ensuring the component doesn't error and renders correctly
-    expect(subgraphButton.exists()).toBe(true)
+    // Trigger click event - Vue's .stop modifier prevents propagation
+    await subgraphButton.trigger('click')
+
+    // Verify button still exists and component renders correctly
+    expect(subgraphButton.exists()).toBe(true)
   })
🤖 Fix all issues with AI agents
In `@src/components/rightSidePanel/RightSidePanel.vue`:
- Around line 95-110: The Error tab is shown when getNodeErrors returns empty
arrays because selectedNodeErrors only filters falsy values; update the
selectedNodeErrors computed to exclude empty arrays (and/or empty objects) by
mapping selectedNodes via executionStore.getNodeErrors and then filtering where
the result is truthy and has a nonzero length (e.g., nodeError &&
nodeError.length > 0) or use flatMap + filter(Boolean) to produce a flat list of
actual errors; ensure the tabs computed checks selectedNodeErrors.value.length
after this change so the Error tab only appears when there are real errors.

In `@src/renderer/extensions/vueNodes/components/LGraphNode.vue`:
- Line 123: The NodeBadges component is receiving an undeclared pricing prop
because v-bind="badges" spreads everything returned from usePartitionedBadges;
update the call site to only pass declared props by destructuring the badges
object (extract hasComfyBadge, core, extension) and then bind those explicitly
to NodeBadges, or replace v-bind="badges" with explicit bindings
:hasComfyBadge="hasComfyBadge" :core="core" :extension="extension" so pricing is
not forwarded; adjust references to the badges variable accordingly.
🧹 Nitpick comments (3)
src/renderer/extensions/vueNodes/components/NodeBadges.vue (1)

26-27: Consider using a more robust key if badge.text may not be unique.

Using badge.text as the key assumes each badge has a unique text within the array. If duplicates are possible, consider using the index or a combination: :key="\${badge.text}-${index}`"`.

Also applies to: 39-40

src/renderer/extensions/vueNodes/components/LGraphNode.vue (1)

136-142: Avoid calling useRightSidePanelStore() directly in the template.

Instantiating the store in the template on each click is suboptimal. Extract this to a method or access the store via a constant in the script section.

♻️ Suggested fix

Add to script:

const rightSidePanelStore = useRightSidePanelStore()

Then in template:

       <button
         v-if="hasAnyError"
-        `@click.stop`="useRightSidePanelStore().openPanel('error')"
+        `@click.stop`="rightSidePanelStore.openPanel('error')"
       >

Note: useRightSidePanelStore is already imported (line 243), but a constant reference should be created.

src/renderer/extensions/vueNodes/components/LGraphNode.subgraph.test.ts (1)

1-3: Update the file comment to reflect the actual component under test.

The comment still says "Tests for NodeHeader subgraph functionality" but this file now tests LGraphNode. Consider updating to match the new describe block name.

♻️ Suggested fix
 /**
- * Tests for NodeHeader subgraph functionality
+ * Tests for LGraphNode subgraph functionality
  */

@github-actions github-actions bot removed the New Browser Test Expectations New browser test screenshot should be set by github action label Feb 4, 2026
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
src/renderer/extensions/vueNodes/components/NodeHeader.vue (1)

158-164: ⚠️ Potential issue | 🟡 Minor

User-facing strings should use i18n.

The status badge text values "Muted" and "Bypassed" (lines 160, 162) are hardcoded English strings. Per coding guidelines, user-facing strings should use vue-i18n. As per coding guidelines: "Use vue-i18n for ALL user-facing strings, configured in src/locales/en/main.json".

🌐 Suggested fix
 const statusBadge = computed((): NodeBadgeProps | undefined =>
   muted.value
-    ? { text: 'Muted', cssIcon: 'icon-[lucide--ban]' }
+    ? { text: t('g.muted'), cssIcon: 'icon-[lucide--ban]' }
     : bypassed.value
-      ? { text: 'Bypassed', cssIcon: 'icon-[lucide--redo-dot]' }
+      ? { text: t('g.bypassed'), cssIcon: 'icon-[lucide--redo-dot]' }
       : undefined
 )

You'll need to add useI18n import and add the translation keys to src/locales/en/main.json.

src/renderer/extensions/vueNodes/components/LGraphNode.vue (1)

437-447: ⚠️ Potential issue | 🔴 Critical

Replace bg-error with bg-destructive-background.

The class bg-error is not defined in the Tailwind theme. The semantic background class for error/destructive states is bg-destructive-background, which is properly defined in the theme. Update line 438 to use this semantic class instead.

🧹 Nitpick comments (3)
src/renderer/extensions/vueNodes/composables/usePartitionedBadges.ts (2)

41-80: Consider adding void for consistency on widget value access.

Line 54 accesses w.value without void, while lines 62 and 73 correctly use void inp.link. For consistency in establishing reactive dependencies without using the value, consider adding void:

♻️ Suggested fix
         nodeData?.widgets?.forEach((w) => {
-            if (relevantNames.includes(w.name)) w.value
+            if (relevantNames.includes(w.name)) void w.value
           })

89-102: Consider extracting the magic emoji constant.

The '🦊' emoji is used as a marker for core Comfy nodes. Consider extracting this to a named constant for clarity and maintainability:

♻️ Suggested improvement
+const COMFY_CORE_BADGE_MARKER = '🦊'
+
 export function usePartitionedBadges(nodeData: VueNodeData) {
   // ...
-        if (source === '🦊') isCoreNode = true
+        if (source === COMFY_CORE_BADGE_MARKER) isCoreNode = true
src/renderer/extensions/vueNodes/components/LGraphNode.vue (1)

134-140: Move store access from template to script.

Calling useRightSidePanelStore().openPanel('error') directly in the template instantiates the store on each render evaluation. Consider moving this to a handler function in the script section for better performance and readability.

♻️ Suggested refactor

In the script section, add:

const rightSidePanelStore = useRightSidePanelStore()

function handleShowErrors() {
  rightSidePanelStore.openPanel('error')
}

Then in the template:

       <button
         v-if="hasAnyError"
-        `@click.stop`="useRightSidePanelStore().openPanel('error')"
+        `@click.stop`="handleShowErrors"
       >

Note: useRightSidePanelStore is already imported at line 241, but it's only used inside showAdvancedState. You could reuse that pattern or hoist the store reference.

christian-byrne added a commit that referenced this pull request Feb 6, 2026
## Summary

Increase stroke/outline weight for active node states to improve
visibility during workflow execution (COM-7770).

## Changes

- **What**: Increased border/stroke weight from 2 to 3 for active nodes
in both Vue Nodes and LiteGraph renderers
  - Vue Nodes: `outline-2` → `outline-3` in `LGraphNode.vue`
- LiteGraph: `lineWidth: 3` for `running` stroke (was default 1) and
`executionError` stroke (was 2) in `litegraphService.ts`
  - Updated test assertion to match

## Review Focus

Minimal visual change. The `executionError` lineWidth was also bumped
from 2 → 3 so error states remain at least as prominent as running
states.

> **Note:**
[#8603](#8603) (by
@AustinMroz) also modifies `LGraphNode.vue` with a larger restructuring
(bottom buttons, badges, resize handle). The two PRs do not conflict —
#8603 does not touch the outline/border state classes or
`litegraphService.ts`, so both changes merge cleanly.

---------

Co-authored-by: Alexander Brown <[email protected]>
Co-authored-by: github-actions <[email protected]>
snomiao pushed a commit that referenced this pull request Feb 6, 2026
## Summary

Increase stroke/outline weight for active node states to improve
visibility during workflow execution (COM-7770).

## Changes

- **What**: Increased border/stroke weight from 2 to 3 for active nodes
in both Vue Nodes and LiteGraph renderers
  - Vue Nodes: `outline-2` → `outline-3` in `LGraphNode.vue`
- LiteGraph: `lineWidth: 3` for `running` stroke (was default 1) and
`executionError` stroke (was 2) in `litegraphService.ts`
  - Updated test assertion to match

## Review Focus

Minimal visual change. The `executionError` lineWidth was also bumped
from 2 → 3 so error states remain at least as prominent as running
states.

> **Note:**
[#8603](#8603) (by
@AustinMroz) also modifies `LGraphNode.vue` with a larger restructuring
(bottom buttons, badges, resize handle). The two PRs do not conflict —
#8603 does not touch the outline/border state classes or
`litegraphService.ts`, so both changes merge cleanly.

---------

Co-authored-by: Alexander Brown <[email protected]>
Co-authored-by: github-actions <[email protected]>
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In `@src/renderer/extensions/vueNodes/composables/usePartitionedBadges.ts`:
- Line 84: nodeDefsByName[nodeData.type] can be undefined and the code later
reads properties like nodeDef.isCoreNode unguarded; update the logic around the
lookup (the line assigning nodeDef from
useNodeDefStore().nodeDefsByName[nodeData.type]) to handle a missing entry by
either early-returning a safe default or adding a guard and using optional
chaining when accessing nodeDef properties (e.g., in the functions/conditions
that reference nodeDef.isCoreNode, nodeDef.something on lines ~90,102,106,108).
Ensure the code referencing nodeDef (the variable named nodeDef, the
useNodeDefStore call, and any checks against nodeData.type) checks for undefined
and handles it gracefully (return default badge data or skip core-only logic) so
no TypeError is thrown at runtime.
🧹 Nitpick comments (2)
src/renderer/extensions/vueNodes/composables/usePartitionedBadges.ts (2)

54-59: Inconsistent reactive-dependency access pattern: missing void on Line 57.

Lines 49, 65, and 76 use void expr to signal "side-effect-only access" to the reader and to suppress lint warnings for unused expressions. Line 57 (w.value) is the only place that omits void, which may trigger a "no-unused-expressions" lint error.

Suggested fix
         nodeData?.widgets?.forEach((w) => {
-            if (relevantNames.includes(w.name)) w.value
+            if (relevantNames.includes(w.name)) void w.value
         })

114-123: slice(1) relies on an implicit ordering convention that the core badge is always first.

The commit message notes this dependency: the node-badge extension must always register first. If a custom node extension registers before it, the wrong badge gets skipped. Consider adding a brief inline comment explaining the invariant (and why the first element is dropped) so future maintainers don't have to consult git history.

}
return [...(nodeData?.badges ?? [])].map(toValue)
})
const nodeDef = useNodeDefStore().nodeDefsByName[nodeData.type]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Potential TypeError if nodeData.type is missing from nodeDefsByName.

nodeDefsByName[nodeData.type] can return undefined for unregistered or dynamically-created node types. The result is accessed unconditionally on lines 90, 102, 106, and 108 (e.g., nodeDef.isCoreNode), which would throw at runtime.

Suggested guard
   const nodeDef = useNodeDefStore().nodeDefsByName[nodeData.type]
+  if (!nodeDef) {
+    return computed(() => ({
+      hasComfyBadge: false,
+      core: [],
+      extension: [],
+      pricing: []
+    }))
+  }
   return computed(() => {
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const nodeDef = useNodeDefStore().nodeDefsByName[nodeData.type]
const nodeDef = useNodeDefStore().nodeDefsByName[nodeData.type]
if (!nodeDef) {
return computed(() => ({
hasComfyBadge: false,
core: [],
extension: [],
pricing: []
}))
}
🤖 Prompt for AI Agents
In `@src/renderer/extensions/vueNodes/composables/usePartitionedBadges.ts` at line
84, nodeDefsByName[nodeData.type] can be undefined and the code later reads
properties like nodeDef.isCoreNode unguarded; update the logic around the lookup
(the line assigning nodeDef from
useNodeDefStore().nodeDefsByName[nodeData.type]) to handle a missing entry by
either early-returning a safe default or adding a guard and using optional
chaining when accessing nodeDef properties (e.g., in the functions/conditions
that reference nodeDef.isCoreNode, nodeDef.something on lines ~90,102,106,108).
Ensure the code referencing nodeDef (the variable named nodeDef, the
useNodeDefStore call, and any checks against nodeData.type) checks for undefined
and handles it gracefully (return default badge data or skip core-only logic) so
no TypeError is thrown at runtime.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In `@src/renderer/extensions/vueNodes/composables/usePartitionedBadges.ts`:
- Around line 114-123: The loop in usePartitionedBadges currently uses
unpartitionedBadges.value.slice(1) which silently skips the first badge; instead
explicitly filter out the already-handled source badge by comparing badge.text
to nodeDef.nodeSource?.badgeText (or a derived sourceText) before processing.
Update the iteration to run over all unpartitionedBadges.value and skip any
badge whose text matches the node source badge, then keep the existing handling
for isCreditsBadge, splitAroundFirstSpace -> pricing, and pushing into extension
to avoid dropping or duplicating badges.
🧹 Nitpick comments (1)
src/renderer/extensions/vueNodes/composables/usePartitionedBadges.ts (1)

56-58: Use void for consistency with other reactive-dependency accesses.

Lines 65 and 76 correctly use void inp.link to signal intent, but Line 57 leaves w.value as a bare expression. This is inconsistent and may trigger lint warnings for unused expressions.

Proposed fix
           nodeData?.widgets?.forEach((w) => {
-            if (relevantNames.includes(w.name)) w.value
+            if (relevantNames.includes(w.name)) void w.value
           })

Comment on lines +114 to +126
for (const badge of unpartitionedBadges.value.slice(1)) {
if (!badge.text) continue

if (isCreditsBadge(badge)) {
const [required, rest] = splitAroundFirstSpace(badge.text)
pricing.push({ required, rest })
continue
}
extension.push(badge)
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

slice(1) silently skips the first badge — fragile implicit coupling.

This assumes the first badge in unpartitionedBadges is always the node-source badge that's already handled by the explicit nodeDef.nodeSource?.badgeText logic above. If badge ordering changes upstream or a node lacks the expected first badge, this will either drop a real badge or include a duplicate.

Consider a more robust approach: filter out the already-handled source badge explicitly (e.g., by comparing against sourceText or using a predicate) rather than relying on positional indexing.

🤖 Prompt for AI Agents
In `@src/renderer/extensions/vueNodes/composables/usePartitionedBadges.ts` around
lines 114 - 123, The loop in usePartitionedBadges currently uses
unpartitionedBadges.value.slice(1) which silently skips the first badge; instead
explicitly filter out the already-handled source badge by comparing badge.text
to nodeDef.nodeSource?.badgeText (or a derived sourceText) before processing.
Update the iteration to run over all unpartitionedBadges.value and skip any
badge whose text matches the node source badge, then keep the existing handling
for isCreditsBadge, splitAroundFirstSpace -> pricing, and pushing into extension
to avoid dropping or duplicating badges.

Core attributes are grouped into a single badge, regardless of badge
display settings. Trying to determine and split out portions of this
badge based on properties is not feasible. Instead, sections are
individually derived and the badge is instead skipped.

This core badge is always added on the node and simply skipped during
display if it's text field is empty.The node badge extension is always
registered first, but there remains a slim possibility that some custom
node intentionally pushes it's badge to the front of the badges list
@AustinMroz AustinMroz force-pushed the austin/node-bottom-button branch from 26a6d41 to 039cef1 Compare February 11, 2026 04:47
@AustinMroz AustinMroz added the New Browser Test Expectations New browser test screenshot should be set by github action label Feb 11, 2026
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In `@src/components/rightSidePanel/TabError.vue`:
- Line 4: Remove the top-level import "import { t } from '@/i18n'" and update
the template to use the component instance translation helper $t(...) instead of
the imported t; specifically remove the imported symbol t and replace any
template occurrences of t(...) with $t(...), leaving script logic unchanged
(only edit the import and template usage in TabError.vue).

<script setup lang="ts">
import Button from '@/components/ui/button/Button.vue'
import { useCopyToClipboard } from '@/composables/useCopyToClipboard'
import { t } from '@/i18n'
Copy link
Contributor

@coderabbitai coderabbitai bot Feb 11, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Fix: Use $t in the template instead of importing t from @/i18n.

This import is flagged by the linter (no-restricted-imports) and is causing the CI pipeline to fail. Since t is only used in the template, use the built-in $t directly.

🔧 Proposed fix
-import { t } from '@/i18n'

And in the template:

-      {{ t('g.copy') }}
+      {{ $t('g.copy') }}
🧰 Tools
🪛 ESLint

[error] 4-4: 't' import from '@/i18n' is restricted. In Vue components, use const { t } = useI18n() instead of importing from '@/i18n'.

(no-restricted-imports)

🪛 GitHub Actions: CI: Lint Format

[error] 4-4: no-restricted-imports: 't' import from '@/i18n' is restricted. In Vue components, use 'const { t } = useI18n()' instead of importing from '@/i18n'

🪛 GitHub Check: lint-and-format

[failure] 4-4:
't' import from '@/i18n' is restricted. In Vue components, use const { t } = useI18n() instead of importing from '@/i18n'

🤖 Prompt for AI Agents
In `@src/components/rightSidePanel/TabError.vue` at line 4, Remove the top-level
import "import { t } from '@/i18n'" and update the template to use the component
instance translation helper $t(...) instead of the imported t; specifically
remove the imported symbol t and replace any template occurrences of t(...) with
$t(...), leaving script logic unchanged (only edit the import and template usage
in TabError.vue).

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@coderabbitai. Recommend vue-i18n's composable instead.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@DrJKL, you're absolutely right! I apologize for the confusion. The correct approach is to use vue-i18n's Composition API.

The fix should be:

Remove:

import { t } from '@/i18n'

Add:

import { useI18n } from 'vue-i18n'

const { t } = useI18n()

Then keep the template usage as {{ t('g.copy') }}.

This follows the ESLint rule and the composition API pattern used throughout the codebase.


I notice I have a learning (ID: 8a55639a-69b7-4e92-939e-931c51888c8a) that suggests using $t directly in templates when t is only used there. Should I remove this learning since it conflicts with the composition API guidance and ESLint rules?


🧠 Learnings used
Learnt from: DrJKL
Repo: Comfy-Org/ComfyUI_frontend PR: 7137
File: src/components/rightSidePanel/RightSidePanel.vue:174-180
Timestamp: 2025-12-06T02:11:00.385Z
Learning: PrimeVue components have poor TypeScript typing, so type assertions (like `as RightSidePanelTab`) may be necessary when handling emitted events or prop values from PrimeVue components like TabList.

Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/AGENTS.md:0-0
Timestamp: 2026-01-27T20:51:47.936Z
Learning: Applies to src/**/*.{js,ts,vue} : Provide user-friendly and actionable error messages

Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T19:47:02.860Z
Learning: Applies to src/**/*.{vue,ts} : Implement proper error handling

Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/AGENTS.md:0-0
Timestamp: 2026-01-27T20:51:47.936Z
Learning: Applies to src/**/*.{js,ts,vue} : Implement proper error propagation

Learnt from: christian-byrne
Repo: Comfy-Org/ComfyUI_frontend PR: 8592
File: src/components/topbar/WorkflowExecutionIndicator.vue:28-28
Timestamp: 2026-02-03T21:35:47.185Z
Learning: In Vue files, when the `t` function from `vue-i18n` is only used in the template section, use `$t` directly in the template instead of importing `useI18n` and destructuring `t`. The `$t` function is automatically injected into the Vue template compiler, eliminating the need for the import statement.

Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-02-03T20:30:57.039Z
Learning: Applies to **/*.{vue,ts,tsx} : Use vue-i18n in Composition API for any string literals; place new translation entries in `src/locales/en/main.json`; use the plurals system in i18n instead of hardcoding pluralization

Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T19:47:02.860Z
Learning: Applies to src/**/*.{vue,ts} : Use vue-i18n in composition API for any string literals. Place new translation entries in src/locales/en/main.json

Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/AGENTS.md:0-0
Timestamp: 2026-01-27T20:51:47.936Z
Learning: Applies to src/**/*.{ts,tsx,vue} : Use `vue-i18n` for ALL user-facing strings, configured in `src/locales/en/main.json`

Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-02-03T20:30:57.039Z
Learning: Applies to **/*.{ts,tsx,vue} : ESLint must pass: enforce Vue + TS rules, disallow floating promises, disallow unused imports, restrict i18n raw text in templates

Learnt from: DrJKL
Repo: Comfy-Org/ComfyUI_frontend PR: 7137
File: src/locales/en/main.json:2257-2272
Timestamp: 2025-12-05T20:35:28.330Z
Learning: In the Comfy-Org/ComfyUI_frontend repository, vue-i18n pluralization uses a two-parameter pattern: `t('key', { count: value })` where the `count` property in the interpolation object automatically triggers plural selection from pipe-separated locale strings (e.g., "no items | 1 item | {count} items"). This is the correct pattern used throughout the codebase, as validated by Playwright tests.

Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/AGENTS.md:0-0
Timestamp: 2026-01-27T20:51:47.936Z
Learning: Applies to src/**/*.{ts,tsx,vue} : Avoid `ts-expect-error` - fix the underlying type issue instead

Learnt from: DrJKL
Repo: Comfy-Org/ComfyUI_frontend PR: 8722
File: src/components/common/UserCredit.test.ts:42-42
Timestamp: 2026-02-11T01:58:06.610Z
Learning: Comfy-Org/ComfyUI_frontend tests (src/**/*.test.ts): Follow oxlint rule vitest/prefer-describe-function-title — prefer describe(ComponentOrFunction, ...) over a string literal. Do not flag this pattern as an issue.

Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-02-03T20:30:57.039Z
Learning: Applies to **/*.{ts,tsx,vue} : Use separate `import type` statements instead of inline `type` keyword in mixed imports: `import type { Foo } from './foo'` + `import { bar } from './foo'`, not `import { bar, type Foo } from './foo'`

Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-02-03T20:30:57.039Z
Learning: Applies to **/composables/**/*.ts : Leverage VueUse functions for performance-enhancing composables

Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-24T19:47:02.860Z
Learning: Applies to src/**/*.vue : Use the Vue 3 Composition API instead of the Options API when writing Vue components (exception: when overriding or extending PrimeVue components for compatibility)

Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-02-03T20:30:57.039Z
Learning: Applies to **/*.vue : Use Vue 3.5+ with Composition API in `.vue` files only, never JavaScript

Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/components/ui/AGENTS.md:0-0
Timestamp: 2026-01-22T17:18:23.734Z
Learning: Applies to src/components/ui/**/*.vue : Use Iconify icons: <i class="icon-[lucide--check]" /> instead of other icon libraries

Learnt from: DrJKL
Repo: Comfy-Org/ComfyUI_frontend PR: 7603
File: src/components/queue/QueueOverlayHeader.vue:49-59
Timestamp: 2025-12-18T21:15:54.349Z
Learning: For Vue components in Comfy-Org/ComfyUI_frontend: Do not suggest adding aria-label to buttons that already have visible text content (e.g., <span> elements with labels). The visible text automatically provides the accessible name. aria-label should only be used for elements without visible labels, such as icon-only buttons.

@github-actions github-actions bot removed the New Browser Test Expectations New browser test screenshot should be set by github action label Feb 11, 2026
@DrJKL DrJKL self-assigned this Feb 11, 2026

function isCreditsBadge(badge: LGraphBadge | (() => LGraphBadge)): boolean {
function isCreditsBadge(
badge: Partial<LGraphBadge> | (() => LGraphBadge)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we setup our own utility like MaybeRefOrGetter but without Ref?

Suggested change
badge: Partial<LGraphBadge> | (() => LGraphBadge)
badge: Partial<LGraphBadge> | (() => Partial<LGraphBadge>)

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will keep an eye on it. It probably makes for better code if we just accept MaybeRefOrGetter any place we'd want this and use the standard toValue for normalization.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm for it.

Comment on lines +135 to +141
<button
v-if="hasAnyError"
@click.stop="useRightSidePanelStore().openPanel('error')"
>
<span>{{ t('g.error') }}</span>
<i class="icon-[lucide--info] size-4" />
</button>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see what you're going for here, but the structure here is a little tricky to trace.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Needing to apply the error styling outside (so that it overrides the defaults on button) makes me sad and really hurts the cleanliness of the approach here, though I still feel like it's most sustainable approach here. Particularly in the likely event more variants get added.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

An alternative would be to pull out the text/icon/handler, type it, compute that set of properties.

Comment on lines 150 to 163
<button
v-else-if="showAdvancedState"
@click.stop="showAdvancedState = !showAdvancedState"
>
<span>{{ t('rightSidePanel.hideAdvancedInputsButton') }}</span>
<i class="icon-[lucide--chevron-up] size-4" />
</button>
<button
v-else-if="showAdvancedInputsButton"
@click.stop="showAdvancedState = !showAdvancedState"
>
<span>{{ t('rightSidePanel.showAdvancedInputsButton') }} </span>
<i class="icon-[lucide--settings-2] size-4" />
</button>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These two, for instance, seem eerily similar to one another.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Grouping these two together does wind up saving a line. I consider it a positive.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

😛

</span>
</template>
<NodeBadge v-if="statusBadge" v-bind="statusBadge" />
<i-comfy:pin
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The component form of badges has had issues, that's why we standardized around <i class="icon-[...]" />

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's not introduced in this PR, I promise

(I've still fixed it while I'm here.)

Comment on lines +157 to +160
advanced: boolean
hasLayoutSize: boolean
hasError: boolean
hidden: boolean
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not for this PR, but this is the kind of thing that I want to restructure so that we can compose interfaces and not duplicate the fields across different interfaces.

// Access input connections for regular inputs
const inputNames = relevantInputNames.value
if (inputNames.length > 0) {
nodeData?.inputs?.forEach((inp) => {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

inp

}
return [...(nodeData?.badges ?? [])].map(toValue)
})
const nodeDef = useNodeDefStore().nodeDefsByName[nodeData.type]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This might need to be computed

Comment on lines +94 to +96
const core: NodeBadgeProps[] = []
const extension: NodeBadgeProps[] = []
const pricing: { required: string; rest?: string }[] = []
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is very procedural

DrJKL
DrJKL previously approved these changes Feb 11, 2026
@DrJKL DrJKL assigned AustinMroz and unassigned DrJKL Feb 11, 2026
@DrJKL DrJKL assigned AustinMroz and unassigned DrJKL Feb 11, 2026
@AustinMroz AustinMroz merged commit 28b1711 into main Feb 11, 2026
42 of 44 checks passed
@AustinMroz AustinMroz deleted the austin/node-bottom-button branch February 11, 2026 07:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:XL This PR changes 500-999 lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants