Skip to content

Conversation

@AustinMroz
Copy link
Collaborator

@AustinMroz AustinMroz commented Nov 27, 2025

Continuation of #6034 with

  • Updated synchronization for seed
  • Properly truncates the displayed widget value for the button
  • Synchronizes control after generate state with litegraph and allows for serialization

Several issues from original PR have not (yet) been addressed, but are likely better moved to future PR

image

┆Issue is synchronized with this Notion page by Unito

christian-byrne and others added 12 commits November 11, 2025 11:49
The @PointerUp.stop was breaking reka ui NumberFields.

IIRC, this was added to allow selecting text without dragging nodes.
Current testing suggests this isn't required for pointerup

This reduces the margins some on number inputs. It's trivial to add a
px-2.5, but helps with information density
@dosubot dosubot bot added the size:XXL This PR changes 1000+ lines, ignoring generated files. label Nov 27, 2025
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Nov 27, 2025

Important

Review skipped

Review was skipped due to path filters

⛔ Files ignored due to path filters (17)
  • browser_tests/tests/vueNodes/groups/groups.spec.ts-snapshots/vue-groups-create-group-chromium-linux.png is excluded by !**/*.png
  • browser_tests/tests/vueNodes/groups/groups.spec.ts-snapshots/vue-groups-fit-to-contents-chromium-linux.png is excluded by !**/*.png
  • browser_tests/tests/vueNodes/interactions/canvas/zoom.spec.ts-snapshots/zoomed-in-ctrl-shift-chromium-linux.png is excluded by !**/*.png
  • browser_tests/tests/vueNodes/interactions/links/linkInteraction.spec.ts-snapshots/vue-node-dragging-link-chromium-linux.png is excluded by !**/*.png
  • browser_tests/tests/vueNodes/interactions/links/linkInteraction.spec.ts-snapshots/vue-node-input-drag-ctrl-alt-chromium-linux.png is excluded by !**/*.png
  • browser_tests/tests/vueNodes/interactions/links/linkInteraction.spec.ts-snapshots/vue-node-input-drag-reuses-origin-chromium-linux.png is excluded by !**/*.png
  • browser_tests/tests/vueNodes/interactions/links/linkInteraction.spec.ts-snapshots/vue-node-reroute-input-drag-chromium-linux.png is excluded by !**/*.png
  • browser_tests/tests/vueNodes/interactions/links/linkInteraction.spec.ts-snapshots/vue-node-reroute-output-shift-drag-chromium-linux.png is excluded by !**/*.png
  • browser_tests/tests/vueNodes/interactions/links/linkInteraction.spec.ts-snapshots/vue-node-shift-output-multi-link-chromium-linux.png is excluded by !**/*.png
  • browser_tests/tests/vueNodes/interactions/links/linkInteraction.spec.ts-snapshots/vue-node-snap-to-node-chromium-linux.png is excluded by !**/*.png
  • browser_tests/tests/vueNodes/interactions/links/linkInteraction.spec.ts-snapshots/vue-node-snap-to-slot-chromium-linux.png is excluded by !**/*.png
  • browser_tests/tests/vueNodes/interactions/node/move.spec.ts-snapshots/vue-node-moved-node-chromium-linux.png is excluded by !**/*.png
  • browser_tests/tests/vueNodes/nodeStates/bypass.spec.ts-snapshots/vue-node-bypassed-state-chromium-linux.png is excluded by !**/*.png
  • browser_tests/tests/vueNodes/nodeStates/colors.spec.ts-snapshots/vue-node-custom-color-blue-chromium-linux.png is excluded by !**/*.png
  • browser_tests/tests/vueNodes/nodeStates/colors.spec.ts-snapshots/vue-node-custom-colors-dark-all-colors-chromium-linux.png is excluded by !**/*.png
  • browser_tests/tests/vueNodes/nodeStates/colors.spec.ts-snapshots/vue-node-custom-colors-light-all-colors-chromium-linux.png is excluded by !**/*.png
  • browser_tests/tests/vueNodes/nodeStates/mute.spec.ts-snapshots/vue-node-muted-state-chromium-linux.png is excluded by !**/*.png

CodeRabbit blocks several paths by default. You can override this behavior by explicitly including those paths in the path filters. For example, including **/dist/** will override the default block on the dist directory, by removing the pattern from both the lists.

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

📝 Walkthrough

Walkthrough

Adds a number-control system: new control widget types and types, UI components and composables to set/apply control modes, a registry to run controls before/after generation, a global seed store, test coverage, and hooks into the app queue flow.

Changes

Cohort / File(s) Summary
Types
src/types/simplifiedWidget.ts
Adds ControlWidgetOptions union and SafeControlWidget type; extends SimplifiedWidget with optional controlWidget?: SafeControlWidget.
Graph mapping
src/composables/graph/useGraphNodeManager.ts
Extends SafeWidgetData with controlWidget; adds helpers to derive/validate control widget data from linked control_after_generate widgets.
Number-control composables
src/renderer/extensions/vueNodes/widgets/composables/useStepperControl.ts, src/renderer/extensions/vueNodes/widgets/composables/useNumberStepCalculation.ts, src/renderer/extensions/vueNodes/widgets/composables/useControlButtonIcon.ts
Adds useStepperControl (with NumberControlMode enum and registry integration), useNumberStepCalculation for step resolution, and useControlButtonIcon for icon mapping.
Widget linking
src/renderer/extensions/vueNodes/widgets/composables/useIntWidget.ts, .../useFloatWidget.ts, .../useComboWidget.ts
Link value-control widgets when inputSpec.control_after_generate is true via addValueControlWidget, attaching them as widget.linkedWidgets.
Registry & global state
src/renderer/extensions/vueNodes/widgets/services/NumberControlRegistry.ts, src/stores/globalSeedStore.ts
Adds NumberControlRegistry singleton with register/unregister/executeControls and useGlobalSeedStore Pinia store for a global seed.
UI components
src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberWithControl.vue, NumberControlPopover.vue, WidgetInputNumber.vue, WidgetInputNumberInput.vue, WidgetInputNumberSlider.vue
New WidgetInputNumberWithControl and NumberControlPopover; WidgetInputNumber renders with control when present; input/slider updated for slot support and step calculation.
Renderer & layout
src/renderer/extensions/vueNodes/components/NodeWidgets.vue, src/renderer/extensions/vueNodes/widgets/components/layout/WidgetLayoutField.vue, src/renderer/extensions/vueNodes/widgets/components/WidgetSelectDropdown.vue
Exposes controlWidget in simplified widget payload; removes @pointerup.stop from layout; normalizes dropdown items logic.
App integration
src/scripts/app.ts
Calls executeNumberControls('before') and executeNumberControls('after') around prompt queue processing.
Localization
src/locales/en/main.json
Adds widgets.numberControl localization keys (headers, link/randomize/increment/decrement, edit settings).
Utilities
src/scripts/utils.ts
Removes specific JSDoc tags and adds browser-only dynamic import to assign window.downloadBlob when available.
Tests & browser tests
tests-ui/.../useStepperControl.test.ts, .../NumberControlRegistry.test.ts, .../globalSeedStore.test.ts, .../useWidgetRenderer.test.ts, browser_tests/...
Adds unit tests for stepper control, registry, global seed; updates widget renderer tests and browser fixtures to ensure deterministic selection.

Sequence Diagram

sequenceDiagram
    participant User
    participant WidgetInputNumberWithControl
    participant NumberControlPopover
    participant useStepperControl
    participant NumberControlRegistry
    participant GlobalSeedStore
    participant app

    User->>WidgetInputNumberWithControl: click control button
    WidgetInputNumberWithControl->>NumberControlPopover: togglePopover()
    User->>NumberControlPopover: select control mode
    NumberControlPopover-->>WidgetInputNumberWithControl: emit update:control-mode
    WidgetInputNumberWithControl->>useStepperControl: setControlMode(newMode)

    Note over User,app: During prompt queuing
    User->>app: queuePrompt()
    app->>NumberControlRegistry: executeNumberControls('before')
    NumberControlRegistry->>useStepperControl: invoke registered applyControl callbacks

    alt INCREMENT/DECREMENT
        useStepperControl->>WidgetInputNumberWithControl: apply step change
    else RANDOMIZE
        useStepperControl->>GlobalSeedStore: read seed
        useStepperControl->>WidgetInputNumberWithControl: apply random value
    else LINK_TO_GLOBAL
        useStepperControl->>GlobalSeedStore: read & clamp seed
        useStepperControl->>WidgetInputNumberWithControl: apply clamped seed
    else FIXED
        Note right of useStepperControl: no-op
    end

    app->>NumberControlRegistry: executeNumberControls('after')
Loading

Possibly related PRs

✨ Finishing touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch austin/vue-control-after-generate

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

@github-actions
Copy link

github-actions bot commented Nov 27, 2025

🎨 Storybook Build Status

Build completed successfully!

⏰ Completed at: 12/05/2025, 12:42:00 AM UTC

🔗 Links


🎉 Your Storybook is ready for review!

@github-actions
Copy link

github-actions bot commented Nov 27, 2025

🎭 Playwright Test Results

⚠️ Tests passed with flaky tests

⏰ Completed at: 12/05/2025, 12:50:53 AM UTC

📈 Summary

  • Total Tests: 495
  • Passed: 482 ✅
  • Failed: 0
  • Flaky: 3 ⚠️
  • Skipped: 10 ⏭️

📊 Test Reports by Browser

  • chromium: View Report • ✅ 473 / ❌ 0 / ⚠️ 3 / ⏭️ 10
  • chromium-2x: View Report • ✅ 2 / ❌ 0 / ⚠️ 0 / ⏭️ 0
  • chromium-0.5x: View Report • ✅ 1 / ❌ 0 / ⚠️ 0 / ⏭️ 0
  • mobile-chrome: View Report • ✅ 6 / ❌ 0 / ⚠️ 0 / ⏭️ 0

🎉 Click on the links above to view detailed test results for each browser configuration.

@github-actions
Copy link

github-actions bot commented Nov 27, 2025

Bundle Size Report

Summary

  • Raw size: 17.1 MB baseline 17 MB — 🔴 +18 kB
  • Gzip: 3.38 MB baseline 3.38 MB — 🔴 +4.76 kB
  • Brotli: 2.59 MB baseline 2.59 MB — 🔴 +4.21 kB
  • Bundles: 98 current • 97 baseline • 40 added / 39 removed

Category Glance
Other 🔴 +7.51 kB (3.82 MB) · UI Components 🔴 +7 kB (180 kB) · App Entry Points 🔴 +2.77 kB (3.2 MB) · Graph Workspace 🔴 +729 B (975 kB) · Vendor & Third-Party ⚪ 0 B (8.56 MB) · Panels & Settings ⚪ 0 B (298 kB) · + 3 more

Per-category breakdown
App Entry Points — 3.2 MB (baseline 3.2 MB) • 🔴 +2.77 kB

Main entry bundles and manifests

File Before After Δ Raw Δ Gzip Δ Brotli
assets/index-BfTPtXD8.js (new) 2.98 MB 🔴 +2.98 MB 🔴 +620 kB 🔴 +471 kB
assets/index-Dqv_ZOH_.js (removed) 2.97 MB 🟢 -2.97 MB 🟢 -619 kB 🟢 -470 kB
assets/index-BvJiT8_B.js (new) 223 kB 🔴 +223 kB 🔴 +47.6 kB 🔴 +39.3 kB
assets/index-CSi1adXo.js (removed) 223 kB 🟢 -223 kB 🟢 -47.6 kB 🟢 -39.3 kB
assets/index-Bftg6aun.js (new) 345 B 🔴 +345 B 🔴 +242 B 🔴 +200 B
assets/index-Ci-KN8RO.js (removed) 345 B 🟢 -345 B 🟢 -246 B 🟢 -230 B

Status: 3 added / 3 removed

Graph Workspace — 975 kB (baseline 974 kB) • 🔴 +729 B

Graph editor runtime, canvas, workflow orchestration

File Before After Δ Raw Δ Gzip Δ Brotli
assets/GraphView-CVTsGZUE.js (new) 975 kB 🔴 +975 kB 🔴 +188 kB 🔴 +144 kB
assets/GraphView-CPctgGIL.js (removed) 974 kB 🟢 -974 kB 🟢 -188 kB 🟢 -143 kB

Status: 1 added / 1 removed

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

Top-level views, pages, and routed surfaces

File Before After Δ Raw Δ Gzip Δ Brotli
assets/UserSelectView-B2S3RyFZ.js (removed) 6.54 kB 🟢 -6.54 kB 🟢 -2.14 kB 🟢 -1.9 kB
assets/UserSelectView-BIJG1tvr.js (new) 6.54 kB 🔴 +6.54 kB 🔴 +2.14 kB 🔴 +1.89 kB

Status: 1 added / 1 removed

Panels & Settings — 298 kB (baseline 298 kB) • ⚪ 0 B

Configuration panels, inspectors, and settings screens

File Before After Δ Raw Δ Gzip Δ Brotli
assets/CreditsPanel-BthBVbtA.js (new) 21.4 kB 🔴 +21.4 kB 🔴 +5.15 kB 🔴 +4.5 kB
assets/CreditsPanel-tdtMHtbU.js (removed) 21.4 kB 🟢 -21.4 kB 🟢 -5.15 kB 🟢 -4.5 kB
assets/KeybindingPanel-BVghyXx8.js (new) 13.6 kB 🔴 +13.6 kB 🔴 +3.42 kB 🔴 +3.02 kB
assets/KeybindingPanel-CjGfBaFT.js (removed) 13.6 kB 🟢 -13.6 kB 🟢 -3.42 kB 🟢 -3.01 kB
assets/ExtensionPanel-DyYQdLIX.js (new) 10.8 kB 🔴 +10.8 kB 🔴 +2.57 kB 🔴 +2.26 kB
assets/ExtensionPanel-zstOuiY7.js (removed) 10.8 kB 🟢 -10.8 kB 🟢 -2.57 kB 🟢 -2.26 kB
assets/AboutPanel-8WSdk0Z1.js (removed) 9.16 kB 🟢 -9.16 kB 🟢 -2.46 kB 🟢 -2.21 kB
assets/AboutPanel-D4UVjzxp.js (new) 9.16 kB 🔴 +9.16 kB 🔴 +2.46 kB 🔴 +2.21 kB
assets/ServerConfigPanel-CkzHihHg.js (removed) 6.56 kB 🟢 -6.56 kB 🟢 -1.83 kB 🟢 -1.63 kB
assets/ServerConfigPanel-DOFDamqH.js (new) 6.56 kB 🔴 +6.56 kB 🔴 +1.83 kB 🔴 +1.63 kB
assets/UserPanel-CJcVIPEn.js (new) 6.23 kB 🔴 +6.23 kB 🔴 +1.72 kB 🔴 +1.51 kB
assets/UserPanel-DHgtcXJW.js (removed) 6.23 kB 🟢 -6.23 kB 🟢 -1.72 kB 🟢 -1.51 kB
assets/settings-BhbWhsRg.js 101 B 101 B ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/settings-BXTtSH4O.js 33.3 kB 33.3 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/settings-C9Pzn-NG.js 25.2 kB 25.2 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/settings-CCy2fA_h.js 27.3 kB 27.3 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/settings-CQpqEFfl.js 26.6 kB 26.6 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/settings-DHcnxypw.js 21.7 kB 21.7 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/settings-DhFTK9fY.js 25.1 kB 25.1 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/settings-DlT4t_ui.js 25.9 kB 25.9 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/settings-DRgSrIdD.js 24.2 kB 24.2 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/settings-tjkeqiZq.js 21.1 kB 21.1 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B

Status: 6 added / 6 removed

UI Components — 180 kB (baseline 173 kB) • 🔴 +7 kB

Reusable component library chunks

File Before After Δ Raw Δ Gzip Δ Brotli
assets/Load3D.vue_vue_type_script_setup_true_lang-D3use3ER.js (removed) 53.9 kB 🟢 -53.9 kB 🟢 -8.52 kB 🟢 -7.32 kB
assets/Load3D.vue_vue_type_script_setup_true_lang-wd7YFEC-.js (new) 53.9 kB 🔴 +53.9 kB 🔴 +8.52 kB 🔴 +7.32 kB
assets/WidgetSelect.vue_vue_type_script_setup_true_lang-CdhKNttT.js (removed) 47.6 kB 🟢 -47.6 kB 🟢 -10.3 kB 🟢 -8.9 kB
assets/WidgetSelect.vue_vue_type_script_setup_true_lang-98vh2mWZ.js (new) 47.6 kB 🔴 +47.6 kB 🔴 +10.2 kB 🔴 +8.88 kB
assets/LazyImage.vue_vue_type_script_setup_true_lang-C3QZroFT.js (new) 43.3 kB 🔴 +43.3 kB 🔴 +9.68 kB 🔴 +8.45 kB
assets/LazyImage.vue_vue_type_script_setup_true_lang-DvvBfJGk.js (removed) 43.3 kB 🟢 -43.3 kB 🟢 -9.68 kB 🟢 -8.46 kB
assets/WidgetInputNumber.vue_vue_type_script_setup_true_lang-B1aYnYvV.js (new) 20.2 kB 🔴 +20.2 kB 🔴 +5.18 kB 🔴 +4.6 kB
assets/WidgetInputNumber.vue_vue_type_script_setup_true_lang-DD37M5Yp.js (removed) 12.9 kB 🟢 -12.9 kB 🟢 -3.37 kB 🟢 -2.97 kB
assets/ComfyQueueButton-B-gpVFmC.js (new) 8.44 kB 🔴 +8.44 kB 🔴 +2.47 kB 🔴 +2.21 kB
assets/ComfyQueueButton-GFcxiIeL.js (removed) 8.44 kB 🟢 -8.44 kB 🟢 -2.47 kB 🟢 -2.21 kB
assets/WidgetLayoutField.vue_vue_type_script_setup_true_lang-Bb3LZ5y7.js (removed) 2.26 kB 🟢 -2.26 kB 🟢 -876 B 🟢 -759 B
assets/WidgetLayoutField.vue_vue_type_script_setup_true_lang-2aDK9bdc.js (new) 2.07 kB 🔴 +2.07 kB 🔴 +863 B 🔴 +748 B
assets/MediaTitle.vue_vue_type_script_setup_true_lang-JYh4DbA5.js (new) 897 B 🔴 +897 B 🔴 +503 B 🔴 +439 B
assets/MediaTitle.vue_vue_type_script_setup_true_lang-mLBoQ1rc.js (removed) 897 B 🟢 -897 B 🟢 -502 B 🟢 -433 B
assets/UserAvatar.vue_vue_type_script_setup_true_lang-CDkUGVOA.js 1.34 kB 1.34 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/WidgetButton-CbZj9xHx.js 2.04 kB 2.04 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B

Status: 7 added / 7 removed

Data & Services — 12.5 kB (baseline 12.5 kB) • ⚪ 0 B

Stores, services, APIs, and repositories

File Before After Δ Raw Δ Gzip Δ Brotli
assets/keybindingService-C1IEfb9_.js (removed) 7.51 kB 🟢 -7.51 kB 🟢 -1.83 kB 🟢 -1.58 kB
assets/keybindingService-Cmf13qSm.js (new) 7.51 kB 🔴 +7.51 kB 🔴 +1.84 kB 🔴 +1.58 kB
assets/audioService-B1yqA1Mo.js (removed) 2.2 kB 🟢 -2.2 kB 🟢 -961 B 🟢 -821 B
assets/audioService-DiyZygR3.js (new) 2.2 kB 🔴 +2.2 kB 🔴 +960 B 🔴 +823 B
assets/serverConfigStore-uprby_D3.js 2.83 kB 2.83 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B

Status: 2 added / 2 removed

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

Helpers, composables, and utility bundles

File Before After Δ Raw Δ Gzip Δ Brotli
assets/audioUtils-Bd0SXmiA.js (new) 1.41 kB 🔴 +1.41 kB 🔴 +651 B 🔴 +552 B
assets/audioUtils-CrwDOilH.js (removed) 1.41 kB 🟢 -1.41 kB 🟢 -650 B 🟢 -543 B
assets/mathUtil-CTARWQ-l.js 1.07 kB 1.07 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/nodeFilterUtil-CXKCRJ-m.js 460 B 460 B ⚪ 0 B ⚪ 0 B ⚪ 0 B

Status: 1 added / 1 removed

Vendor & Third-Party — 8.56 MB (baseline 8.56 MB) • ⚪ 0 B

External libraries and shared vendor chunks

File Before After Δ Raw Δ Gzip Δ Brotli
assets/vendor-chart-BhMrpT7H.js 452 kB 452 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/vendor-other-Djvsb6Yg.js 3.98 MB 3.98 MB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/vendor-primevue-vP_q3PtU.js 1.96 MB 1.96 MB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/vendor-three-aR6ntw5X.js 1.37 MB 1.37 MB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/vendor-tiptap-abEQAgz5.js 232 kB 232 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/vendor-vue-abso1wrr.js 160 kB 160 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/vendor-xterm-BZLod3g9.js 407 kB 407 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
Other — 3.82 MB (baseline 3.81 MB) • 🔴 +7.51 kB

Bundles that do not match a named category

File Before After Δ Raw Δ Gzip Δ Brotli
assets/WidgetRecordAudio-CgHcKqEH.js (new) 20.4 kB 🔴 +20.4 kB 🔴 +5.24 kB 🔴 +4.63 kB
assets/WidgetRecordAudio-DmFtzdLM.js (removed) 20.4 kB 🟢 -20.4 kB 🟢 -5.24 kB 🟢 -4.63 kB
assets/AudioPreviewPlayer-CmJ8yYTF.js (new) 13.5 kB 🔴 +13.5 kB 🔴 +3.4 kB 🔴 +3.04 kB
assets/AudioPreviewPlayer-Dhj1P9tl.js (removed) 13.5 kB 🟢 -13.5 kB 🟢 -3.4 kB 🟢 -3.05 kB
assets/NumberControlPopover-BloqCqrB.js (new) 7.51 kB 🔴 +7.51 kB 🔴 +2.15 kB 🔴 +1.9 kB
assets/WidgetGalleria-CA7nKdp1.js (removed) 4.1 kB 🟢 -4.1 kB 🟢 -1.44 kB 🟢 -1.3 kB
assets/WidgetGalleria-DT6t2J9o.js (new) 4.1 kB 🔴 +4.1 kB 🔴 +1.44 kB 🔴 +1.3 kB
assets/WidgetColorPicker-BlAeiw_N.js (removed) 3.41 kB 🟢 -3.41 kB 🟢 -1.38 kB 🟢 -1.23 kB
assets/WidgetColorPicker-LLJwrm80.js (new) 3.41 kB 🔴 +3.41 kB 🔴 +1.37 kB 🔴 +1.23 kB
assets/WidgetMarkdown-B58x_myY.js (new) 3.08 kB 🔴 +3.08 kB 🔴 +1.28 kB 🔴 +1.12 kB
assets/WidgetMarkdown-CQos0WjR.js (removed) 3.08 kB 🟢 -3.08 kB 🟢 -1.28 kB 🟢 -1.12 kB
assets/WidgetTextarea-CoXfUnia.js (removed) 2.93 kB 🟢 -2.93 kB 🟢 -1.17 kB 🟢 -1.05 kB
assets/WidgetTextarea-q3dL9krU.js (new) 2.93 kB 🔴 +2.93 kB 🔴 +1.16 kB 🔴 +1.03 kB
assets/WidgetAudioUI-C7HQMFhz.js (removed) 2.82 kB 🟢 -2.82 kB 🟢 -1.12 kB 🟢 -1.01 kB
assets/WidgetAudioUI-gOEkvfn6.js (new) 2.82 kB 🔴 +2.82 kB 🔴 +1.12 kB 🔴 +1.04 kB
assets/WidgetInputText-B2QBLQt9.js (removed) 1.99 kB 🟢 -1.99 kB 🟢 -917 B 🟢 -847 B
assets/WidgetInputText-DtKjoYhK.js (new) 1.99 kB 🔴 +1.99 kB 🔴 +914 B 🔴 +848 B
assets/WidgetToggleSwitch-C8WLR8XC.js (removed) 1.58 kB 🟢 -1.58 kB 🟢 -761 B 🟢 -665 B
assets/WidgetToggleSwitch-DFQ6n4N4.js (new) 1.58 kB 🔴 +1.58 kB 🔴 +761 B 🔴 +668 B
assets/MediaImageBottom-BCGLFTN2.js (new) 1.57 kB 🔴 +1.57 kB 🔴 +743 B 🔴 +647 B
assets/MediaImageBottom-DZ1NlKIm.js (removed) 1.57 kB 🟢 -1.57 kB 🟢 -741 B 🟢 -647 B
assets/MediaAudioBottom-B0OSNze9.js (new) 1.52 kB 🔴 +1.52 kB 🔴 +740 B 🔴 +657 B
assets/MediaAudioBottom-BE1-CE4j.js (removed) 1.52 kB 🟢 -1.52 kB 🟢 -740 B 🟢 -657 B
assets/MediaVideoBottom-BqHSgwzA.js (removed) 1.52 kB 🟢 -1.52 kB 🟢 -738 B 🟢 -655 B
assets/MediaVideoBottom-Do46Aj7N.js (new) 1.52 kB 🔴 +1.52 kB 🔴 +740 B 🔴 +655 B
assets/Media3DBottom-CP2HxaEF.js (new) 1.5 kB 🔴 +1.5 kB 🔴 +733 B 🔴 +650 B
assets/Media3DBottom-DBUol5fK.js (removed) 1.5 kB 🟢 -1.5 kB 🟢 -731 B 🟢 -652 B
assets/Media3DTop-D2AT_UMY.js (removed) 1.49 kB 🟢 -1.49 kB 🟢 -763 B 🟢 -644 B
assets/Media3DTop-DseJMjWG.js (new) 1.49 kB 🔴 +1.49 kB 🔴 +763 B 🔴 +651 B
assets/WidgetSelect-4FFdgevL.js (removed) 655 B 🟢 -655 B 🟢 -343 B 🟢 -288 B
assets/WidgetSelect-CEWB3jKM.js (new) 655 B 🔴 +655 B 🔴 +339 B 🔴 +290 B
assets/WidgetInputNumber-CH18WsAw.js (removed) 595 B 🟢 -595 B 🟢 -330 B 🟢 -276 B
assets/WidgetInputNumber-Ds_21GY2.js (new) 595 B 🔴 +595 B 🔴 +326 B 🔴 +273 B
assets/Load3D-CQLPkBU4.js (new) 424 B 🔴 +424 B 🔴 +268 B 🔴 +224 B
assets/Load3D-jZ0TOmfb.js (removed) 424 B 🟢 -424 B 🟢 -265 B 🟢 -224 B
assets/WidgetLegacy-DOkfbAIG.js (removed) 364 B 🟢 -364 B 🟢 -238 B 🟢 -194 B
assets/WidgetLegacy-fDCrYahw.js (new) 364 B 🔴 +364 B 🔴 +236 B 🔴 +195 B
assets/commands-_s-RvhJR.js 13.6 kB 13.6 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/commands-BuUILW6P.js 13 kB 13 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/commands-BV4R6fLx.js 14.9 kB 14.9 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/commands-BWp4HdfU.js 101 B 101 B ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/commands-CLwPdnT6.js 14.2 kB 14.2 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/commands-CWMchBmd.js 15.9 kB 15.9 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/commands-DazTQhtc.js 12.9 kB 12.9 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/commands-DmWrOe93.js 13.7 kB 13.7 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/commands-DwiH7Kr6.js 13.8 kB 13.8 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/commands-mS3LCNPn.js 14.5 kB 14.5 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/main-B1JflQcI.js 72.2 kB 72.2 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/main-B2lyXe48.js 114 kB 114 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/main-B9XEQ-pc.js 94 kB 94 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/main-BErKFzc-.js 73.1 kB 73.1 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/main-Bf7Tze-u.js 83.4 kB 83.4 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/main-BhGMcO4Q.js 84.3 kB 84.3 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/main-CPZUloNQ.js 99 kB 99 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/main-Cw9RZWRY.js 89 B 89 B ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/main-Dva0z-T2.js 86.5 kB 86.5 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/main-un0K9wDS.js 81.8 kB 81.8 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/MediaAudioTop-DCIZ2mdC.js 1.46 kB 1.46 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/MediaImageTop-Du4uz2Wm.js 1.75 kB 1.75 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/MediaVideoTop-59yKN05c.js 2.76 kB 2.76 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/nodeDefs-8e6QYQW0.js 283 kB 283 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/nodeDefs-A_9dx4yn.js 304 kB 304 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/nodeDefs-BbD3HDi7.js 307 kB 307 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/nodeDefs-BOJhIPft.js 369 kB 369 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/nodeDefs-Bw_Jitw_.js 101 B 101 B ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/nodeDefs-C-Pw33mW.js 317 kB 317 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/nodeDefs-ChLyG0UJ.js 285 kB 285 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/nodeDefs-CUVPxA4l.js 342 kB 342 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/nodeDefs-Dx5Y4xrW.js 310 kB 310 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/nodeDefs-JqO5mNmW.js 306 kB 306 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/WidgetChart-Beblk1io.js 2.48 kB 2.48 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/WidgetImageCompare-CMMfeF2r.js 2.21 kB 2.21 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/widgetPropFilter-BIbGSUAt.js 1.28 kB 1.28 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B

Status: 19 added / 18 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: 3

🧹 Nitpick comments (8)
src/renderer/extensions/vueNodes/widgets/components/WidgetSelectDropdown.vue (2)

148-165: Unified dropdownItems logic looks correct

The refactor to have asset mode always use allItems and non-asset “all” explicitly concatenate inputItems and outputItems is consistent with the surrounding data flow; no functional issues stand out. If you want to reduce duplication, the 'all' branch could just return allItems.value, but that’s purely optional.


70-81: Localize user-facing strings and tighten upload error messaging

Several strings are user-visible but not run through vue-i18n, which conflicts with the repo guidelines:

  • Filter option labels: 'All', 'Inputs', 'Outputs' (Lines 76–79).
  • Toast messages: File upload failed, Upload failed: ${error} (Lines 296, 320).

Consider:

  • Replacing these literals with t(...) calls and adding appropriate entries in src/locales/en/main.json.
  • For the upload error toast, deriving a readable message (e.g. error instanceof Error ? error.message : String(error)) rather than stringifying the raw error object.

This keeps UX consistent and ready for localization without changing behavior.

Also applies to: 263-264, 295-321

tests-ui/tests/stores/globalSeedStore.test.ts (1)

21-28: Consider replacing the probabilistic assertion.

This test relies on random seed generation to be different across store instances, which introduces non-determinism. While the 1-in-1,000,000 chance is low, flaky tests can cause false failures in CI/CD pipelines.

Consider one of these alternatives:

  1. Mock Math.random() to return predictable values
  2. Test that the seed is within the valid range instead of comparing uniqueness
  3. Accept the low flakiness risk and document it clearly

Example with mocking:

 it('should create different seeds for different store instances', () => {
+  const mockRandom = vi.spyOn(Math, 'random')
+  mockRandom.mockReturnValueOnce(0.5)
   const store1 = useGlobalSeedStore()
   setActivePinia(createPinia()) // Reset pinia
+  mockRandom.mockReturnValueOnce(0.7)
   const store2 = useGlobalSeedStore()

-  // Very unlikely to be the same (1 in 1,000,000 chance)
-  expect(store1.globalSeed).not.toBe(store2.globalSeed)
+  expect(store1.globalSeed).toBe(500000)
+  expect(store2.globalSeed).toBe(700000)
+  mockRandom.mockRestore()
 })
src/types/simplifiedWidget.ts (1)

18-26: Consider adding 'link-to-global' to ControlWidgetOptions type.

The NumberControlPopover.vue component references a LINK_TO_GLOBAL mode (currently disabled via feature flag), but this option is missing from the ControlWidgetOptions type union. While the feature is disabled now, including it in the type definition would ensure type safety when the feature is enabled.

 export type ControlWidgetOptions =
   | 'fixed'
   | 'increment'
   | 'decrement'
   | 'randomize'
+  | 'link-to-global'
src/renderer/extensions/vueNodes/widgets/components/NumberControlPopover.vue (1)

29-29: Document the LINK_TO_GLOBAL feature flag.

The ENABLE_LINK_TO_GLOBAL constant is hardcoded to false, but there's no comment explaining why this feature is disabled or what would be required to enable it. Consider adding a comment to guide future development.

+// TODO: Enable LINK_TO_GLOBAL once global seed synchronization is fully implemented
 const ENABLE_LINK_TO_GLOBAL = false
src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberWithControl.vue (1)

57-64: Consider using cn() utility for class merging.

Per coding guidelines, prefer using the cn() utility from @/utils/tailwindUtil for class merging instead of template string interpolation.

-        <i :class="`${controlButtonIcon} text-blue-100 text-xs`" />
+        <i :class="cn(controlButtonIcon, 'text-blue-100 text-xs')" />

You'll need to import cn from @/utils/tailwindUtil.

src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.vue (1)

123-128: Remove potentially dead PrimeVue CSS.

This scoped CSS targets .p-inputnumber-input, a PrimeVue class. Since the component now uses Reka UI's NumberFieldRoot/NumberFieldInput, this CSS may no longer apply and could be removed.

src/renderer/extensions/vueNodes/widgets/services/NumberControlRegistry.ts (1)

27-34: Consider wrapping callback execution in try-catch for resilience.

If one registered applyFn throws an error, it will prevent subsequent controls from being applied. Consider wrapping each callback in a try-catch to ensure all controls are executed.

   executeControls(phase: 'before' | 'after'): void {
     const settingStore = useSettingStore()
     if (settingStore.get('Comfy.WidgetControlMode') === phase) {
       for (const applyFn of this.controls.values()) {
-        applyFn()
+        try {
+          applyFn()
+        } catch (error) {
+          console.error('Error executing number control:', error)
+        }
       }
     }
   }

Comment on lines +54 to +67
if (typeof window !== 'undefined') {
import('@/base/common/downloadUtil')
.then((module) => {
const fn = (
module as {
downloadBlob?: typeof import('@/base/common/downloadUtil').downloadBlob
}
).downloadBlob
if (typeof fn === 'function') {
;(window as any).downloadBlob = fn
}
})
.catch(() => {})
}
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 | 🟠 Major

Fix TypeScript violations: avoid as any and improve error handling.

This code violates two explicit coding guidelines:

  1. Line 63 uses as any type assertion
  2. Line 66 silently swallows errors

As per coding guidelines, never use as any type assertions and implement proper error handling.

Apply this diff to fix both issues:

+declare global {
+  interface Window {
+    downloadBlob?: typeof import('@/base/common/downloadUtil').downloadBlob
+  }
+}
+
 if (typeof window !== 'undefined') {
   import('@/base/common/downloadUtil')
     .then((module) => {
       const fn = (
         module as {
           downloadBlob?: typeof import('@/base/common/downloadUtil').downloadBlob
         }
       ).downloadBlob
       if (typeof fn === 'function') {
-        ;(window as any).downloadBlob = fn
+        window.downloadBlob = fn
       }
     })
-    .catch(() => {})
+    .catch((error) => {
+      console.error('Failed to load downloadBlob utility:', error)
+    })
 }
📝 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
if (typeof window !== 'undefined') {
import('@/base/common/downloadUtil')
.then((module) => {
const fn = (
module as {
downloadBlob?: typeof import('@/base/common/downloadUtil').downloadBlob
}
).downloadBlob
if (typeof fn === 'function') {
;(window as any).downloadBlob = fn
}
})
.catch(() => {})
}
declare global {
interface Window {
downloadBlob?: typeof import('@/base/common/downloadUtil').downloadBlob
}
}
if (typeof window !== 'undefined') {
import('@/base/common/downloadUtil')
.then((module) => {
const fn = (
module as {
downloadBlob?: typeof import('@/base/common/downloadUtil').downloadBlob
}
).downloadBlob
if (typeof fn === 'function') {
window.downloadBlob = fn
}
})
.catch((error) => {
console.error('Failed to load downloadBlob utility:', error)
})
}

@DrJKL DrJKL added the New Browser Test Expectations New browser test screenshot should be set by github action label Nov 27, 2025
@github-actions
Copy link

Updating Playwright Expectations

@github-actions github-actions bot removed the New Browser Test Expectations New browser test screenshot should be set by github action label Nov 27, 2025
@dosubot dosubot bot added size:L This PR changes 100-499 lines, ignoring generated files. and removed size:XXL This PR changes 1000+ lines, ignoring generated files. labels Nov 27, 2025
@dosubot dosubot bot added size:XXL This PR changes 1000+ lines, ignoring generated files. and removed size:XL This PR changes 500-999 lines, ignoring generated files. labels Dec 3, 2025
@AustinMroz AustinMroz added the New Browser Test Expectations New browser test screenshot should be set by github action label Dec 3, 2025
@github-actions github-actions bot removed the New Browser Test Expectations New browser test screenshot should be set by github action label Dec 3, 2025
@dosubot dosubot bot added size:XL This PR changes 500-999 lines, ignoring generated files. and removed size:XXL This PR changes 1000+ lines, ignoring generated files. labels Dec 3, 2025
Playwright locators break because there's now an additional button

Swapping to reka ui introduces a bug where clicking and dragging the
mouse off a button causes the number to change continually. This is hard
to change and I found a workaround to get truncation to work with
primevue instead.
@dosubot dosubot bot added size:XXL This PR changes 1000+ lines, ignoring generated files. and removed size:XL This PR changes 500-999 lines, ignoring generated files. labels Dec 3, 2025
@AustinMroz AustinMroz added the New Browser Test Expectations New browser test screenshot should be set by github action label Dec 3, 2025
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

🧹 Nitpick comments (1)
browser_tests/fixtures/VueNodeHelpers.ts (1)

159-164: Avoid relying on button index; prefer a more specific decrement selector

Switching from last() to nth(1) will correctly skip a trailing control/config button, but this is still fragile: tests now depend on the exact DOM order and button count inside the widget. If the template gains another button or the order changes, nth(1) may stop pointing to the decrement control.

Where possible, prefer a more explicit locator for the decrement button (e.g. a data-testid, role+name, or _vue selector targeting the specific component/prop) rather than its position among all button elements:

// Example shape, assuming markup supports it
decrementButton: widget.getByTestId('number-decrement')
// or
decrementButton: widget.getByRole('button', { name: 'Decrement' })

This will make the tests more stable and aligns with the guidance to use specific selectors in browser tests. Based on learnings, ...

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 9723e2b and ad70768.

📒 Files selected for processing (3)
  • browser_tests/fixtures/VueNodeHelpers.ts (1 hunks)
  • browser_tests/tests/vueNodes/widgets/int/integerWidget.spec.ts (1 hunks)
  • src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.vue (4 hunks)
🧰 Additional context used
📓 Path-based instructions (18)
**/*.{vue,ts,tsx}

📄 CodeRabbit inference engine (.cursorrules)

**/*.{vue,ts,tsx}: Leverage VueUse functions for performance-enhancing utilities
Use vue-i18n in Composition API for any string literals and place new translation entries in src/locales/en/main.json

Files:

  • browser_tests/fixtures/VueNodeHelpers.ts
  • browser_tests/tests/vueNodes/widgets/int/integerWidget.spec.ts
  • src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.vue
**/*.{ts,tsx,js}

📄 CodeRabbit inference engine (.cursorrules)

Use es-toolkit for utility functions

Files:

  • browser_tests/fixtures/VueNodeHelpers.ts
  • browser_tests/tests/vueNodes/widgets/int/integerWidget.spec.ts
**/*.{ts,tsx}

📄 CodeRabbit inference engine (.cursorrules)

Use TypeScript for type safety

**/*.{ts,tsx}: Never use any type - use proper TypeScript types
Never use as any type assertions - fix the underlying type issue

Files:

  • browser_tests/fixtures/VueNodeHelpers.ts
  • browser_tests/tests/vueNodes/widgets/int/integerWidget.spec.ts
**/*.{ts,tsx,js,vue}

📄 CodeRabbit inference engine (.cursorrules)

Implement proper error handling in components and services

**/*.{ts,tsx,js,vue}: Use 2-space indentation, single quotes, no semicolons, and maintain 80-character line width as configured in .prettierrc
Organize imports by sorting and grouping by plugin, and run pnpm format before committing

Files:

  • browser_tests/fixtures/VueNodeHelpers.ts
  • browser_tests/tests/vueNodes/widgets/int/integerWidget.spec.ts
  • src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.vue
**/*.{ts,tsx,js,jsx,vue}

📄 CodeRabbit inference engine (CLAUDE.md)

Use camelCase for variable and setting names in TypeScript/Vue files

Files:

  • browser_tests/fixtures/VueNodeHelpers.ts
  • browser_tests/tests/vueNodes/widgets/int/integerWidget.spec.ts
  • src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.vue
**/*.{ts,tsx,vue}

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.{ts,tsx,vue}: Use const settingStore = useSettingStore() and settingStore.get('Comfy.SomeSetting') to retrieve settings in TypeScript/Vue files
Use await settingStore.set('Comfy.SomeSetting', newValue) to update settings in TypeScript/Vue files
Check server capabilities using api.serverSupportsFeature('feature_name') before using enhanced features
Use api.getServerFeature('config_name', defaultValue) to retrieve server feature configuration

Enforce ESLint rules for Vue + TypeScript including: no floating promises, no unused imports, and i18n raw text restrictions in templates

Files:

  • browser_tests/fixtures/VueNodeHelpers.ts
  • browser_tests/tests/vueNodes/widgets/int/integerWidget.spec.ts
  • src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.vue
**/*.ts

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.ts: Define dynamic setting defaults using runtime context with functions in settings configuration
Use defaultsByInstallVersion property for gradual feature rollout based on version in settings configuration

Files:

  • browser_tests/fixtures/VueNodeHelpers.ts
  • browser_tests/tests/vueNodes/widgets/int/integerWidget.spec.ts
browser_tests/**/*.{e2e,spec}.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (browser_tests/CLAUDE.md)

browser_tests/**/*.{e2e,spec}.{ts,tsx,js,jsx}: Test user workflows in browser tests
Use Playwright fixtures for browser tests
Follow naming conventions for browser tests
Check assets/ directory for test data when writing tests
Prefer specific selectors in browser tests
Test across multiple viewports

Files:

  • browser_tests/tests/vueNodes/widgets/int/integerWidget.spec.ts
**/*.{test,spec}.{ts,tsx,js}

📄 CodeRabbit inference engine (AGENTS.md)

Unit and component tests should be located in tests-ui/ or co-located with components as src/components/**/*.{test,spec}.ts; E2E tests should be in browser_tests/

Files:

  • browser_tests/tests/vueNodes/widgets/int/integerWidget.spec.ts
browser_tests/**/*.{test,spec}.ts

📄 CodeRabbit inference engine (AGENTS.md)

Playwright E2E tests can use optional tags like @mobile and @2x which are respected by the Playwright configuration

Files:

  • browser_tests/tests/vueNodes/widgets/int/integerWidget.spec.ts
**/*.vue

📄 CodeRabbit inference engine (.cursorrules)

**/*.vue: Use setup() function for component logic in Vue 3 Composition API
Utilize ref and reactive for reactive state in Vue 3
Implement computed properties with computed() function
Use watch and watchEffect for side effects in Vue 3
Implement lifecycle hooks with onMounted, onUpdated, etc.
Utilize provide/inject for dependency injection in Vue 3
Use Vue 3.5 style of default prop declaration with defineProps()
Organize Vue components in <script> <style> order
Use Tailwind CSS for styling Vue components
Implement responsive design with Tailwind CSS
Do not use deprecated PrimeVue components (Dropdown, OverlayPanel, Calendar, InputSwitch, Sidebar, Chips, TabMenu, Steps, InlineMessage). Use replacements: Select, Popover, DatePicker, ToggleSwitch, Drawer, AutoComplete, Tabs, Stepper, Message respectively
Implement proper props and emits definitions in Vue components
Utilize Vue 3's Teleport component when needed
Use Suspense for async components in Vue 3
Follow Vue 3 style guide and naming conventions
Never use deprecated PrimeVue components (Dropdown, OverlayPanel, Calendar, InputSwitch, Sidebar, Chips, TabMenu, Steps, InlineMessage)

Never use :class="[]" to merge class names - always use import { cn } from '@/utils/tailwindUtil' for class merging in Vue templates

**/*.vue: Use TypeScript with Vue 3 Single File Components (.vue files)
Name Vue components in PascalCase (e.g., MenuHamburger.vue)

Files:

  • src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.vue
src/**/*.vue

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

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)
Use setup() function for component logic
Utilize ref and reactive for reactive state
Implement computed properties with computed()
Use watch and watchEffect for side effects
Implement lifecycle hooks with onMounted, onUpdated, etc.
Utilize provide/inject for dependency injection
Use vue 3.5 style of default prop declaration
Use Tailwind CSS for styling
Implement proper props and emits definitions
Utilize Vue 3's Teleport component when needed
Use Suspense for async components
Follow Vue 3 style guide and naming conventions

Files:

  • src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.vue
src/**/*.{vue,ts}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

src/**/*.{vue,ts}: Leverage VueUse functions for performance-enhancing styles
Implement proper error handling
Use vue-i18n in composition API for any string literals. Place new translation entries in src/locales/en/main.json

Files:

  • src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.vue
**/*.{vue,html}

📄 CodeRabbit inference engine (CLAUDE.md)

Never use dark: or dark-theme: Tailwind variants - instead use semantic values from style.css theme, e.g. bg-node-component-surface

Files:

  • src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.vue
src/**/*.{ts,tsx,vue}

📄 CodeRabbit inference engine (src/CLAUDE.md)

src/**/*.{ts,tsx,vue}: Sanitize HTML with DOMPurify to prevent XSS attacks
Avoid using @ts-expect-error; use proper TypeScript types instead
Use es-toolkit for utility functions instead of other utility libraries
Implement proper TypeScript types throughout the codebase

Files:

  • src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.vue
src/**/{composables,components}/**/*.{ts,tsx,vue}

📄 CodeRabbit inference engine (src/CLAUDE.md)

Clean up subscriptions in state management to prevent memory leaks

Files:

  • src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.vue
src/**/*.{vue,ts,tsx}

📄 CodeRabbit inference engine (src/CLAUDE.md)

Follow Vue 3 composition API style guide

Files:

  • src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.vue
src/**/{components,composables}/**/*.{ts,tsx,vue}

📄 CodeRabbit inference engine (src/CLAUDE.md)

Use vue-i18n for ALL user-facing strings by adding them to src/locales/en/main.json

Files:

  • src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.vue
🧠 Learnings (14)
📚 Learning: 2025-11-24T19:47:45.616Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/components/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:45.616Z
Learning: Applies to src/components/**/*.vue : Replace PrimeVue InputSwitch component with ToggleSwitch

Applied to files:

  • browser_tests/fixtures/VueNodeHelpers.ts
  • src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.vue
📚 Learning: 2025-11-24T19:48:03.270Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: tests-ui/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:48:03.270Z
Learning: Applies to tests-ui/**/*.test.{js,ts,jsx,tsx} : Write tests for new features

Applied to files:

  • browser_tests/fixtures/VueNodeHelpers.ts
  • browser_tests/tests/vueNodes/widgets/int/integerWidget.spec.ts
📚 Learning: 2025-11-24T19:47:22.909Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: browser_tests/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:22.909Z
Learning: Applies to browser_tests/**/*.{e2e,spec}.{ts,tsx,js,jsx} : Prefer specific selectors in browser tests

Applied to files:

  • browser_tests/fixtures/VueNodeHelpers.ts
  • browser_tests/tests/vueNodes/widgets/int/integerWidget.spec.ts
📚 Learning: 2025-11-24T19:46:52.279Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: .cursorrules:0-0
Timestamp: 2025-11-24T19:46:52.279Z
Learning: Applies to **/*.vue : Do not use deprecated PrimeVue components (Dropdown, OverlayPanel, Calendar, InputSwitch, Sidebar, Chips, TabMenu, Steps, InlineMessage). Use replacements: Select, Popover, DatePicker, ToggleSwitch, Drawer, AutoComplete, Tabs, Stepper, Message respectively

Applied to files:

  • browser_tests/fixtures/VueNodeHelpers.ts
  • src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.vue
📚 Learning: 2025-11-24T19:48:03.270Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: tests-ui/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:48:03.270Z
Learning: Applies to tests-ui/**/*.test.{js,ts,jsx,tsx} : Follow existing test patterns in the codebase

Applied to files:

  • browser_tests/tests/vueNodes/widgets/int/integerWidget.spec.ts
📚 Learning: 2025-11-24T19:47:02.860Z
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} : Leverage VueUse functions for performance-enhancing styles

Applied to files:

  • src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.vue
📚 Learning: 2025-11-24T19:46:52.279Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: .cursorrules:0-0
Timestamp: 2025-11-24T19:46:52.279Z
Learning: Applies to **/*.vue : Never use deprecated PrimeVue components (Dropdown, OverlayPanel, Calendar, InputSwitch, Sidebar, Chips, TabMenu, Steps, InlineMessage)

Applied to files:

  • src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.vue
📚 Learning: 2025-11-24T19:47:45.616Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/components/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:45.616Z
Learning: Applies to src/components/**/*.vue : Replace PrimeVue Steps component with Stepper without panels

Applied to files:

  • src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.vue
📚 Learning: 2025-11-24T19:47:45.616Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/components/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:45.616Z
Learning: Applies to src/components/**/*.vue : Use setup() function in Vue 3 Composition API

Applied to files:

  • src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.vue
📚 Learning: 2025-11-24T19:47:45.616Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/components/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:45.616Z
Learning: Applies to src/components/**/*.vue : Implement computed() for derived state in Vue 3 Composition API

Applied to files:

  • src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.vue
📚 Learning: 2025-11-24T19:46:52.279Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: .cursorrules:0-0
Timestamp: 2025-11-24T19:46:52.279Z
Learning: Applies to **/*.vue : Implement computed properties with computed() function

Applied to files:

  • src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.vue
📚 Learning: 2025-11-24T19:47:02.860Z
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 : Implement computed properties with computed()

Applied to files:

  • src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.vue
📚 Learning: 2025-11-24T19:46:52.279Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: .cursorrules:0-0
Timestamp: 2025-11-24T19:46:52.279Z
Learning: Applies to **/*.{vue,ts,tsx} : Leverage VueUse functions for performance-enhancing utilities

Applied to files:

  • src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.vue
📚 Learning: 2025-11-24T19:46:52.279Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: .cursorrules:0-0
Timestamp: 2025-11-24T19:46:52.279Z
Learning: Applies to **/*.vue : Use setup() function for component logic in Vue 3 Composition API

Applied to files:

  • src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.vue
🪛 ESLint
src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.vue

[error] 3-3: Unable to resolve path to module 'vue'.

(import-x/no-unresolved)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (6)
  • GitHub Check: deploy-and-comment
  • GitHub Check: setup
  • GitHub Check: collect
  • GitHub Check: test
  • GitHub Check: setup
  • GitHub Check: lint-and-format
🔇 Additional comments (2)
browser_tests/tests/vueNodes/widgets/int/integerWidget.spec.ts (1)

18-20: The .first() selector is appropriate and improves code explicitness.

The workflow contains only one KSampler node, making the explicit .first() call safe and deterministic. This aligns with Playwright best practices for clear widget selection in tests.

src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.vue (1)

3-3: ESLint import-x/no-unresolved on 'vue' is likely configuration-related

import { computed, useSlots } from 'vue' is the standard Vue 3 import. If ESLint is flagging this as unresolved, it’s almost certainly an import/resolver or dependency setup issue rather than a code problem. Please verify that vue is installed and that your ESLint resolver is configured to work with your bundler/TypeScript setup.

Comment on lines +72 to +80
const slots = useSlots()
const inputClass = computed(() =>
cn(
'[&>input]:bg-transparent [&>input]:border-0',
'[&>input]:truncate [&>input]:min-w-[4ch]',
slots.default && '[&>input]:pr-7'
)
)
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

Avoid always-rendered overlay div that can block input interaction

The useSlots + inputClass approach to add right padding when a default slot exists is solid, but the absolutely positioned wrapper:

<div class="absolute top-5 right-8 h-4 w-7 -translate-y-4/5">
  <slot />
</div>

renders unconditionally. When no default slot is provided, this creates an invisible box over the input’s top‑right area, which can intercept clicks/focus without showing any control.

You can align behavior with inputClass by only rendering the wrapper when a default slot is present:

-    <div class="absolute top-5 right-8 h-4 w-7 -translate-y-4/5">
-      <slot />
-    </div>
+    <div
+      v-if="slots.default"
+      class="absolute top-5 right-8 h-4 w-7 -translate-y-4/5"
+    >
+      <slot />
+    </div>

This keeps the overlay and extra padding in sync and avoids an invisible hitbox when no control is slotted in.

Also applies to: 100-103, 119-121

🤖 Prompt for AI Agents
In
src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.vue
around lines 72-80 (and similarly at 100-103 and 119-121), the absolutely
positioned wrapper divs are rendered unconditionally and can create an invisible
hitbox when no default slot is provided; make those wrapper divs render only
when a default slot exists by guarding them with a conditional (e.g.
v-if="slots.default" or v-if="$slots.default" depending on script setup/context)
so the overlay appears only when the slot is present and stays in sync with the
inputClass padding logic.

@github-actions github-actions bot removed the New Browser Test Expectations New browser test screenshot should be set by github action label Dec 3, 2025
@dosubot dosubot bot added size:L This PR changes 100-499 lines, ignoring generated files. and removed size:XXL This PR changes 1000+ lines, ignoring generated files. labels Dec 3, 2025
@dosubot dosubot bot added size:XL This PR changes 500-999 lines, ignoring generated files. and removed size:L This PR changes 100-499 lines, ignoring generated files. labels Dec 5, 2025
@AustinMroz AustinMroz added New Browser Test Expectations New browser test screenshot should be set by github action size:L This PR changes 100-499 lines, ignoring generated files. and removed size:XL This PR changes 500-999 lines, ignoring generated files. labels Dec 5, 2025
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

📜 Review details

Configuration used: CodeRabbit UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between ad70768 and 0b5ded8.

⛔ Files ignored due to path filters (11)
  • browser_tests/tests/vueNodes/groups/groups.spec.ts-snapshots/vue-groups-fit-to-contents-chromium-linux.png is excluded by !**/*.png
  • browser_tests/tests/vueNodes/interactions/links/linkInteraction.spec.ts-snapshots/vue-node-dragging-link-chromium-linux.png is excluded by !**/*.png
  • browser_tests/tests/vueNodes/interactions/links/linkInteraction.spec.ts-snapshots/vue-node-input-drag-ctrl-alt-chromium-linux.png is excluded by !**/*.png
  • browser_tests/tests/vueNodes/interactions/links/linkInteraction.spec.ts-snapshots/vue-node-input-drag-reuses-origin-chromium-linux.png is excluded by !**/*.png
  • browser_tests/tests/vueNodes/interactions/links/linkInteraction.spec.ts-snapshots/vue-node-reroute-input-drag-chromium-linux.png is excluded by !**/*.png
  • browser_tests/tests/vueNodes/interactions/links/linkInteraction.spec.ts-snapshots/vue-node-reroute-output-shift-drag-chromium-linux.png is excluded by !**/*.png
  • browser_tests/tests/vueNodes/interactions/links/linkInteraction.spec.ts-snapshots/vue-node-shift-output-multi-link-chromium-linux.png is excluded by !**/*.png
  • browser_tests/tests/vueNodes/interactions/links/linkInteraction.spec.ts-snapshots/vue-node-snap-to-node-chromium-linux.png is excluded by !**/*.png
  • browser_tests/tests/vueNodes/interactions/links/linkInteraction.spec.ts-snapshots/vue-node-snap-to-slot-chromium-linux.png is excluded by !**/*.png
  • browser_tests/tests/vueNodes/nodeStates/colors.spec.ts-snapshots/vue-node-custom-colors-dark-all-colors-chromium-linux.png is excluded by !**/*.png
  • browser_tests/tests/vueNodes/nodeStates/colors.spec.ts-snapshots/vue-node-custom-colors-light-all-colors-chromium-linux.png is excluded by !**/*.png
📒 Files selected for processing (3)
  • src/locales/en/main.json (1 hunks)
  • src/renderer/extensions/vueNodes/widgets/components/layout/WidgetLayoutField.vue (0 hunks)
  • src/scripts/app.ts (3 hunks)
💤 Files with no reviewable changes (1)
  • src/renderer/extensions/vueNodes/widgets/components/layout/WidgetLayoutField.vue
🧰 Additional context used
📓 Path-based instructions (11)
**/*.{vue,ts,tsx}

📄 CodeRabbit inference engine (.cursorrules)

**/*.{vue,ts,tsx}: Leverage VueUse functions for performance-enhancing utilities
Use vue-i18n in Composition API for any string literals and place new translation entries in src/locales/en/main.json

Files:

  • src/scripts/app.ts
**/*.{ts,tsx,js}

📄 CodeRabbit inference engine (.cursorrules)

Use es-toolkit for utility functions

Files:

  • src/scripts/app.ts
**/*.{ts,tsx}

📄 CodeRabbit inference engine (.cursorrules)

Use TypeScript for type safety

**/*.{ts,tsx}: Never use any type - use proper TypeScript types
Never use as any type assertions - fix the underlying type issue

Files:

  • src/scripts/app.ts
**/*.{ts,tsx,js,vue}

📄 CodeRabbit inference engine (.cursorrules)

Implement proper error handling in components and services

**/*.{ts,tsx,js,vue}: Use 2-space indentation, single quotes, no semicolons, and maintain 80-character line width as configured in .prettierrc
Organize imports by sorting and grouping by plugin, and run pnpm format before committing

Files:

  • src/scripts/app.ts
src/**/*.{vue,ts}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

src/**/*.{vue,ts}: Leverage VueUse functions for performance-enhancing styles
Implement proper error handling
Use vue-i18n in composition API for any string literals. Place new translation entries in src/locales/en/main.json

Files:

  • src/scripts/app.ts
src/**/*.ts

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

src/**/*.ts: Use es-toolkit for utility functions
Use TypeScript for type safety

Files:

  • src/scripts/app.ts
**/*.{ts,tsx,js,jsx,vue}

📄 CodeRabbit inference engine (CLAUDE.md)

Use camelCase for variable and setting names in TypeScript/Vue files

Files:

  • src/scripts/app.ts
**/*.{ts,tsx,vue}

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.{ts,tsx,vue}: Use const settingStore = useSettingStore() and settingStore.get('Comfy.SomeSetting') to retrieve settings in TypeScript/Vue files
Use await settingStore.set('Comfy.SomeSetting', newValue) to update settings in TypeScript/Vue files
Check server capabilities using api.serverSupportsFeature('feature_name') before using enhanced features
Use api.getServerFeature('config_name', defaultValue) to retrieve server feature configuration

Enforce ESLint rules for Vue + TypeScript including: no floating promises, no unused imports, and i18n raw text restrictions in templates

Files:

  • src/scripts/app.ts
**/*.ts

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.ts: Define dynamic setting defaults using runtime context with functions in settings configuration
Use defaultsByInstallVersion property for gradual feature rollout based on version in settings configuration

Files:

  • src/scripts/app.ts
src/**/*.{ts,tsx,vue}

📄 CodeRabbit inference engine (src/CLAUDE.md)

src/**/*.{ts,tsx,vue}: Sanitize HTML with DOMPurify to prevent XSS attacks
Avoid using @ts-expect-error; use proper TypeScript types instead
Use es-toolkit for utility functions instead of other utility libraries
Implement proper TypeScript types throughout the codebase

Files:

  • src/scripts/app.ts
src/**/*.{vue,ts,tsx}

📄 CodeRabbit inference engine (src/CLAUDE.md)

Follow Vue 3 composition API style guide

Files:

  • src/scripts/app.ts
🧬 Code graph analysis (1)
src/scripts/app.ts (1)
src/renderer/extensions/vueNodes/widgets/services/NumberControlRegistry.ts (1)
  • executeNumberControls (57-59)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (6)
  • GitHub Check: deploy-and-comment
  • GitHub Check: setup
  • GitHub Check: setup
  • GitHub Check: lint-and-format
  • GitHub Check: collect
  • GitHub Check: test
🔇 Additional comments (3)
src/scripts/app.ts (3)

34-34: Import placement and dependency layering look good

The new executeNumberControls import follows the existing pattern of pulling renderer/vueNodes utilities into app.ts (we already import ensureCorrectLayoutScale from the same area), so this dependency direction is consistent and there’s no unused import issue here.


1345-1358: Confirm intended scope and timing of executeNumberControls('before')

executeNumberControls('before') now runs once per batch iteration, after all beforeQueued widget callbacks (main graph + subgraphs) and immediately before graphToPrompt. That means:

  • Controls see the post‑widget state of the graph and affect the prompt that is just about to be queued.
  • The hook runs regardless of whether any number controls are actually registered, assuming the registry is a safe no‑op in that case.
  • For partial executions (queueNodeIds), the hook still runs globally and doesn’t filter by the nodes being executed.

Please double‑check that this ordering and global scope match the intended design for number controls (especially for control‑before‑generate vs control‑after‑generate modes and partial execution flows). If you want controls to be able to key off which nodes will run, they may need access to p or queueNodeIds here.


1396-1408: Clarify executeNumberControls('after') behavior on errors and partial failures

executeNumberControls('after') is invoked only when api.queuePrompt resolves successfully; it is skipped when an exception is thrown because the break inside the catch exits the loop before reaching this call. It still runs when res.node_errors is non‑empty.

This seems reasonable (don’t run “after” controls when the prompt wasn’t queued at all), but it does mean:

  • Any “after‑generate” behavior will not run on PromptExecutionError even if prior hooks (e.g. before) have already adjusted state.
  • “After” hooks will still run when the backend reports node‑level errors in res.node_errors.

Please confirm that this matches the intended UX for control‑after‑generate, especially around failed/partial executions; if you expect symmetrical cleanup or state updates on certain error paths, we may want to call executeNumberControls('after') in a narrower finally around queuePrompt or gate it explicitly on res.prompt_id / lastNodeErrors.

Comment on lines +1914 to 1929
"numberControl": {
"controlHeaderBefore": "Automatically update the value",
"controlHeaderAfter": "AFTER",
"controlHeaderBefore2": "BEFORE",
"controlHeaderEnd": "running the workflow:",
"linkToGlobal": "Link to",
"linkToGlobalSeed": "Global Value",
"linkToGlobalDesc": "Unique value linked to the Global Value's control setting",
"randomize": "Randomize Value",
"randomizeDesc": "Shuffles the value randomly after each generation",
"increment": "Increment Value",
"incrementDesc": "Adds 1 to the value number",
"decrement": "Decrement Value",
"decrementDesc": "Subtracts 1 from the value number",
"editSettings": "Edit control settings"
}
Copy link
Contributor

Choose a reason for hiding this comment

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

🧹 Nitpick | 🔵 Trivial

Clarify inconsistent capitalization and key naming in number control strings.

Lines 1915-1916 show inconsistent capitalization: controlHeaderBefore uses mixed case ("Automatically update the value"), while controlHeaderAfter and controlHeaderBefore2 use ALL CAPS ("AFTER", "BEFORE"). This inconsistency suggests either an error or unclear intent about how these strings are displayed.

Additionally, using both controlHeaderBefore and controlHeaderBefore2 as key names is confusing—why does one have a "2" suffix? If these are meant to be alternative headers or parts of the same phrase (e.g., a sentence fragment), use more descriptive names (e.g., controlModePrefix, controlModeAfter, controlModeBefore, controlModeSuffix) to clarify their purpose.

Please verify:

  1. Why controlHeaderBefore and controlHeaderBefore2 have different naming; clarify if one should be renamed.
  2. How these strings are composed in the Vue component—do they concatenate into a grammatically correct sentence?
  3. Ensure capitalization is intentional (ALL CAPS for mode labels vs. mixed case for descriptions).
🤖 Prompt for AI Agents
In src/locales/en/main.json around lines 1914 to 1929, the keys
controlHeaderBefore and controlHeaderBefore2 are confusing and capitalization is
inconsistent (mixed case vs ALL CAPS); rename keys to expressive names (e.g.,
controlModeBefore, controlModeAfter, controlModePrefix, controlModeSuffix) to
reflect their roles, standardize string capitalization (use ALL CAPS only for
mode labels or mixed case for descriptive text consistently), update the Vue
component to read the new keys and concatenate them into a single grammatically
correct sentence (ensure spacing/punctuation when joining fragments), and remove
the numeric suffix key name; confirm these changes across all locale files and
component usages.

@github-actions github-actions bot removed the New Browser Test Expectations New browser test screenshot should be set by github action label Dec 5, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

claude-review Add to trigger a PR code review from Claude Code size:L This PR changes 100-499 lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants