feat(cloud): redesign the cloud onboarding survey#13518
Conversation
Lead with an intent question that branches into a builder follow-up, trim familiarity to three levels, group the acquisition source with a social platform branch, and add free-text "other" on intent and source. Options carry an optional icon.
Replace the radio and checkbox rows with selectable cards, auto-advance on single-select, and render the survey on a dark surface so it reads on the onboarding background.
Widen intent to allow a single value and add the new field ids, keeping the legacy fields so existing analytics stay intact.
Assert card selection, single-click auto-advance, branch reveal and hiding, "other" free-text gating, and interaction-gated errors, plus the default schema's branching.
Force the flag on, prefer the frontend schema over the backend, and bypass the completed check so the redesign is visible during review. Revert before merge.
- Retheme cards, inputs, and buttons to comfy-canvas tokens; animate step height and cross-fade transitions; hide the hero on survey routes - Branch source into source_social and gate focus behind builder intents; surface field errors only after interaction
🎭 Playwright: ⏳ Running...🎨 Storybook: ✅ Built — View Storybook📦 Bundle: 7.78 MB gzip 🔴 +1.24 kBDetailsSummary
Category Glance App Entry Points — 47.8 kB (baseline 47.8 kB) • ⚪ 0 BMain entry bundles and manifests
Status: 1 added / 1 removed Graph Workspace — 1.27 MB (baseline 1.27 MB) • ⚪ 0 BGraph editor runtime, canvas, workflow orchestration
Status: 1 added / 1 removed Views & Navigation — 104 kB (baseline 98 kB) • 🔴 +5.75 kBTop-level views, pages, and routed surfaces
Status: 9 added / 9 removed / 3 unchanged Panels & Settings — 546 kB (baseline 546 kB) • ⚪ 0 BConfiguration panels, inspectors, and settings screens
Status: 11 added / 11 removed / 16 unchanged User & Accounts — 29.1 kB (baseline 29.1 kB) • ⚪ 0 BAuthentication, profile, and account management bundles
Status: 7 added / 7 removed / 3 unchanged Editors & Dialogs — 117 kB (baseline 117 kB) • ⚪ 0 BModals, dialogs, drawers, and in-app editors
Status: 4 added / 4 removed / 1 unchanged UI Components — 57.5 kB (baseline 57.5 kB) • ⚪ 0 BReusable component library chunks
Status: 5 added / 5 removed / 8 unchanged Data & Services — 270 kB (baseline 270 kB) • ⚪ 0 BStores, services, APIs, and repositories
Status: 13 added / 13 removed / 3 unchanged Utilities & Hooks — 3.38 MB (baseline 3.38 MB) • ⚪ 0 BHelpers, composables, and utility bundles
Status: 19 added / 19 removed / 14 unchanged Vendor & Third-Party — 15.3 MB (baseline 15.3 MB) • ⚪ 0 BExternal libraries and shared vendor chunks Status: 16 unchanged Other — 11.7 MB (baseline 11.7 MB) • 🟢 -84 BBundles that do not match a named category
Status: 75 added / 75 removed / 90 unchanged ⚡ Performance Report
Show regressions
All metrics
Historical variance (last 15 runs)
Trend (last 15 commits on main)
Raw data{
"timestamp": "2026-07-08T18:38:54.115Z",
"gitSha": "dfc305149075786fadaef57d7e7aca3c9752c876",
"branch": "feat/onboarding-survey-redesign",
"measurements": [
{
"name": "canvas-idle",
"durationMs": 2040.2280000000133,
"styleRecalcs": 9,
"styleRecalcDurationMs": 8.699000000000002,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 440.2900000000001,
"heapDeltaBytes": -3393240,
"heapUsedBytes": 49638676,
"domNodes": -288,
"jsHeapTotalBytes": 17166336,
"scriptDurationMs": 20.44,
"eventListeners": -197,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.799999999999272
},
{
"name": "canvas-idle",
"durationMs": 2088.0039999999553,
"styleRecalcs": 9,
"styleRecalcDurationMs": 14.153,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 509.277,
"heapDeltaBytes": -7525016,
"heapUsedBytes": 62071676,
"domNodes": -283,
"jsHeapTotalBytes": 19021824,
"scriptDurationMs": 24.138,
"eventListeners": -199,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.799999999999272
},
{
"name": "canvas-mouse-sweep",
"durationMs": 2147.884000000033,
"styleRecalcs": 83,
"styleRecalcDurationMs": 58.85499999999999,
"layouts": 12,
"layoutDurationMs": 4.099,
"taskDurationMs": 1047.414,
"heapDeltaBytes": -12700040,
"heapUsedBytes": 56887772,
"domNodes": -238,
"jsHeapTotalBytes": 19021824,
"scriptDurationMs": 140.159,
"eventListeners": -199,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.799999999999272
},
{
"name": "canvas-mouse-sweep",
"durationMs": 1822.6809999999887,
"styleRecalcs": 75,
"styleRecalcDurationMs": 41.049,
"layouts": 12,
"layoutDurationMs": 3.528,
"taskDurationMs": 861.178,
"heapDeltaBytes": -13126108,
"heapUsedBytes": 56422356,
"domNodes": -240,
"jsHeapTotalBytes": 19808256,
"scriptDurationMs": 123.00500000000001,
"eventListeners": -199,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.700000000000728
},
{
"name": "canvas-zoom-sweep",
"durationMs": 1757.8300000000127,
"styleRecalcs": 30,
"styleRecalcDurationMs": 21.223,
"layouts": 6,
"layoutDurationMs": 0.833,
"taskDurationMs": 385.192,
"heapDeltaBytes": -3620776,
"heapUsedBytes": 65911412,
"domNodes": -222,
"jsHeapTotalBytes": 12730368,
"scriptDurationMs": 24.81,
"eventListeners": -184,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.66333333333332,
"p95FrameDurationMs": 16.700000000000728
},
{
"name": "canvas-zoom-sweep",
"durationMs": 1726.0539999999764,
"styleRecalcs": 31,
"styleRecalcDurationMs": 17.895999999999997,
"layouts": 6,
"layoutDurationMs": 0.7010000000000001,
"taskDurationMs": 367.698,
"heapDeltaBytes": -1994116,
"heapUsedBytes": 50062868,
"domNodes": -241,
"jsHeapTotalBytes": 10088448,
"scriptDurationMs": 22.779,
"eventListeners": -186,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.66333333333332,
"p95FrameDurationMs": 16.700000000000728
},
{
"name": "dom-widget-clipping",
"durationMs": 619.1910000000007,
"styleRecalcs": 11,
"styleRecalcDurationMs": 8.527999999999999,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 404.574,
"heapDeltaBytes": 3372732,
"heapUsedBytes": 55442936,
"domNodes": -291,
"jsHeapTotalBytes": 11399168,
"scriptDurationMs": 56.868,
"eventListeners": -201,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.700000000000728
},
{
"name": "dom-widget-clipping",
"durationMs": 606.5250000000333,
"styleRecalcs": 12,
"styleRecalcDurationMs": 11.052,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 390.91900000000004,
"heapDeltaBytes": 2578816,
"heapUsedBytes": 72139316,
"domNodes": -283,
"jsHeapTotalBytes": 5128192,
"scriptDurationMs": 60.275,
"eventListeners": -203,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.66333333333332,
"p95FrameDurationMs": 16.799999999999272
},
{
"name": "large-graph-idle",
"durationMs": 2052.708999999993,
"styleRecalcs": 8,
"styleRecalcDurationMs": 8.455,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 674.292,
"heapDeltaBytes": -25437448,
"heapUsedBytes": 59204764,
"domNodes": -271,
"jsHeapTotalBytes": 3219456,
"scriptDurationMs": 112.07899999999998,
"eventListeners": -199,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.66333333333332,
"p95FrameDurationMs": 16.700000000000728
},
{
"name": "large-graph-idle",
"durationMs": 2044.9709999999186,
"styleRecalcs": 9,
"styleRecalcDurationMs": 8.84,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 689.039,
"heapDeltaBytes": -9141660,
"heapUsedBytes": 57863628,
"domNodes": -271,
"jsHeapTotalBytes": -1323008,
"scriptDurationMs": 106.80199999999999,
"eventListeners": -199,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.66333333333332,
"p95FrameDurationMs": 16.800000000000182
},
{
"name": "large-graph-pan",
"durationMs": 2116.160999999977,
"styleRecalcs": 67,
"styleRecalcDurationMs": 18.375999999999998,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 1101.134,
"heapDeltaBytes": 20251412,
"heapUsedBytes": 81318344,
"domNodes": -281,
"jsHeapTotalBytes": -888832,
"scriptDurationMs": 379.776,
"eventListeners": -197,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.66333333333332,
"p95FrameDurationMs": 16.700000000000728
},
{
"name": "large-graph-pan",
"durationMs": 2109.414000000015,
"styleRecalcs": 68,
"styleRecalcDurationMs": 19.155,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 1126.77,
"heapDeltaBytes": 21087096,
"heapUsedBytes": 82156772,
"domNodes": -278,
"jsHeapTotalBytes": -626688,
"scriptDurationMs": 377.992,
"eventListeners": -197,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.66333333333335,
"p95FrameDurationMs": 16.700000000000728
},
{
"name": "large-graph-zoom",
"durationMs": 3097.445999999991,
"styleRecalcs": 62,
"styleRecalcDurationMs": 17.820000000000004,
"layouts": 60,
"layoutDurationMs": 8.62,
"taskDurationMs": 1357.9399999999998,
"heapDeltaBytes": 13847452,
"heapUsedBytes": 68735952,
"domNodes": 4,
"jsHeapTotalBytes": 0,
"scriptDurationMs": 519.1719999999999,
"eventListeners": 8,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.700000000000728
},
{
"name": "large-graph-zoom",
"durationMs": 3085.546000000022,
"styleRecalcs": 62,
"styleRecalcDurationMs": 17.464,
"layouts": 60,
"layoutDurationMs": 8.511,
"taskDurationMs": 1311.636,
"heapDeltaBytes": 11884596,
"heapUsedBytes": 65836828,
"domNodes": -281,
"jsHeapTotalBytes": 0,
"scriptDurationMs": 487.803,
"eventListeners": 8,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.66333333333332,
"p95FrameDurationMs": 16.699999999999818
},
{
"name": "minimap-idle",
"durationMs": 2037.0910000000322,
"styleRecalcs": 7,
"styleRecalcDurationMs": 6.8980000000000015,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 648.5479999999999,
"heapDeltaBytes": -2632752,
"heapUsedBytes": 59418396,
"domNodes": -276,
"jsHeapTotalBytes": -831488,
"scriptDurationMs": 110.32700000000001,
"eventListeners": -197,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.700000000000728
},
{
"name": "minimap-idle",
"durationMs": 2027.398000000062,
"styleRecalcs": 7,
"styleRecalcDurationMs": 5.842,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 592.945,
"heapDeltaBytes": -3167280,
"heapUsedBytes": 58680324,
"domNodes": -274,
"jsHeapTotalBytes": -1617920,
"scriptDurationMs": 98.52199999999999,
"eventListeners": -199,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.670000000000012,
"p95FrameDurationMs": 16.800000000000182
},
{
"name": "subgraph-dom-widget-clipping",
"durationMs": 605.9349999999881,
"styleRecalcs": 47,
"styleRecalcDurationMs": 11.838000000000001,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 399.003,
"heapDeltaBytes": 10130776,
"heapUsedBytes": 62887804,
"domNodes": -290,
"jsHeapTotalBytes": 6680576,
"scriptDurationMs": 123.873,
"eventListeners": -197,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.66333333333332,
"p95FrameDurationMs": 16.700000000000728
},
{
"name": "subgraph-dom-widget-clipping",
"durationMs": 610.5159999999614,
"styleRecalcs": 47,
"styleRecalcDurationMs": 12.118999999999998,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 416.9870000000001,
"heapDeltaBytes": 19739164,
"heapUsedBytes": 72091636,
"domNodes": -279,
"jsHeapTotalBytes": -397312,
"scriptDurationMs": 125.32199999999999,
"eventListeners": -197,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.700000000000728
},
{
"name": "subgraph-idle",
"durationMs": 2007.472000000007,
"styleRecalcs": 10,
"styleRecalcDurationMs": 10.024,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 447.86800000000005,
"heapDeltaBytes": 4251760,
"heapUsedBytes": 67932152,
"domNodes": 20,
"jsHeapTotalBytes": 15204352,
"scriptDurationMs": 20.269999999999996,
"eventListeners": 4,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.700000000000728
},
{
"name": "subgraph-idle",
"durationMs": 2008.4439999999404,
"styleRecalcs": 10,
"styleRecalcDurationMs": 9.346,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 479.493,
"heapDeltaBytes": 18461108,
"heapUsedBytes": 71033736,
"domNodes": -287,
"jsHeapTotalBytes": 16904192,
"scriptDurationMs": 20.264999999999997,
"eventListeners": -199,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.66333333333332,
"p95FrameDurationMs": 16.700000000000728
},
{
"name": "subgraph-mouse-sweep",
"durationMs": 1763.6400000000094,
"styleRecalcs": 79,
"styleRecalcDurationMs": 41.891999999999996,
"layouts": 16,
"layoutDurationMs": 4.943,
"taskDurationMs": 752.912,
"heapDeltaBytes": 15803936,
"heapUsedBytes": 67841040,
"domNodes": -277,
"jsHeapTotalBytes": 12185600,
"scriptDurationMs": 100.00399999999999,
"eventListeners": -199,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.700000000000728
},
{
"name": "subgraph-mouse-sweep",
"durationMs": 1743.8680000000204,
"styleRecalcs": 77,
"styleRecalcDurationMs": 43.94199999999999,
"layouts": 16,
"layoutDurationMs": 4.77,
"taskDurationMs": 782.778,
"heapDeltaBytes": -16983664,
"heapUsedBytes": 52694212,
"domNodes": -231,
"jsHeapTotalBytes": 19283968,
"scriptDurationMs": 100.438,
"eventListeners": -199,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.700000000000728
},
{
"name": "subgraph-transition-enter",
"durationMs": 1250.0230000000556,
"styleRecalcs": 18,
"styleRecalcDurationMs": 32.559999999999995,
"layouts": 14,
"layoutDurationMs": 14.96,
"taskDurationMs": 937.2450000000001,
"heapDeltaBytes": 8428496,
"heapUsedBytes": 98852412,
"domNodes": 12231,
"jsHeapTotalBytes": 10760192,
"scriptDurationMs": 36.576,
"eventListeners": 844,
"totalBlockingTimeMs": 142,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.699999999999818
},
{
"name": "viewport-pan-sweep",
"durationMs": 8207.902999999988,
"styleRecalcs": 251,
"styleRecalcDurationMs": 62.50399999999999,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 3874.9410000000003,
"heapDeltaBytes": 2899748,
"heapUsedBytes": 69857536,
"domNodes": -266,
"jsHeapTotalBytes": 1241088,
"scriptDurationMs": 1222.167,
"eventListeners": -183,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.700000000000728
},
{
"name": "viewport-pan-sweep",
"durationMs": 8222.375000000056,
"styleRecalcs": 249,
"styleRecalcDurationMs": 62.808,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 3832.772,
"heapDeltaBytes": 8801076,
"heapUsedBytes": 69116556,
"domNodes": -279,
"jsHeapTotalBytes": 1732608,
"scriptDurationMs": 1233.9900000000002,
"eventListeners": -183,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.799999999999272
},
{
"name": "vue-large-graph-idle",
"durationMs": 13667.771999999957,
"styleRecalcs": 0,
"styleRecalcDurationMs": 0,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 13643.955,
"heapDeltaBytes": -52260412,
"heapUsedBytes": 169811072,
"domNodes": -3300,
"jsHeapTotalBytes": 3670016,
"scriptDurationMs": 527.803,
"eventListeners": -16374,
"totalBlockingTimeMs": 0,
"frameDurationMs": 17.226666666666762,
"p95FrameDurationMs": 16.700000000000728
},
{
"name": "vue-large-graph-idle",
"durationMs": 13688.728000000083,
"styleRecalcs": 0,
"styleRecalcDurationMs": 0,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 13673.599999999999,
"heapDeltaBytes": -43083132,
"heapUsedBytes": 176096804,
"domNodes": -3301,
"jsHeapTotalBytes": 3903488,
"scriptDurationMs": 565.52,
"eventListeners": -16381,
"totalBlockingTimeMs": 0,
"frameDurationMs": 17.220000000000073,
"p95FrameDurationMs": 16.799999999999272
},
{
"name": "vue-large-graph-pan",
"durationMs": 16506.294000000024,
"styleRecalcs": 100,
"styleRecalcDurationMs": 23.82200000000001,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 16480.896999999997,
"heapDeltaBytes": -70603860,
"heapUsedBytes": 156771488,
"domNodes": -8311,
"jsHeapTotalBytes": 17502208,
"scriptDurationMs": 846.708,
"eventListeners": -16368,
"totalBlockingTimeMs": 16,
"frameDurationMs": 17.219999999999953,
"p95FrameDurationMs": 16.80000000000291
},
{
"name": "vue-large-graph-pan",
"durationMs": 16303.579000000012,
"styleRecalcs": 90,
"styleRecalcDurationMs": 22.785999999999973,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 16280.506000000003,
"heapDeltaBytes": -36366332,
"heapUsedBytes": 168352904,
"domNodes": -3300,
"jsHeapTotalBytes": 1544192,
"scriptDurationMs": 840.8129999999999,
"eventListeners": -16376,
"totalBlockingTimeMs": 7,
"frameDurationMs": 17.776666666666642,
"p95FrameDurationMs": 16.799999999999272
},
{
"name": "workflow-execution",
"durationMs": 503.78699999998844,
"styleRecalcs": 16,
"styleRecalcDurationMs": 26.958,
"layouts": 5,
"layoutDurationMs": 1.633,
"taskDurationMs": 169.517,
"heapDeltaBytes": -2100272,
"heapUsedBytes": 51538844,
"domNodes": -133,
"jsHeapTotalBytes": -135168,
"scriptDurationMs": 18.923000000000002,
"eventListeners": -134,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.66666666666665,
"p95FrameDurationMs": 16.700000000000728
},
{
"name": "workflow-execution",
"durationMs": 209.80499999996027,
"styleRecalcs": 14,
"styleRecalcDurationMs": 25.305999999999997,
"layouts": 4,
"layoutDurationMs": 1.542,
"taskDurationMs": 199.471,
"heapDeltaBytes": -24161616,
"heapUsedBytes": 46641424,
"domNodes": 148,
"jsHeapTotalBytes": 5914624,
"scriptDurationMs": 16.276,
"eventListeners": -191,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.700000000000728
}
]
} |
|
Note Currently processing new changes in this PR. This may take a few minutes, please wait... ⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: ASSERTIVE Plan: Pro Plus Run ID: 📒 Files selected for processing (4)
📝 WalkthroughWalkthroughRedesigns the cloud onboarding survey with updated schema and branching, revised field and form interactions, route-controlled hero visibility, refreshed survey view styling, and new locale content. ChangesCloud Onboarding Survey Redesign
Estimated code review effort: 4 (Complex) | ~60 minutes Suggested labels: Suggested reviewers: Important Pre-merge checks failedPlease resolve all errors before merging. Addressing warnings is optional. ❌ Failed checks (1 inconclusive)
✅ Passed checks (5 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
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. Comment |
Codecov Report❌ Patch coverage is @@ Coverage Diff @@
## main #13518 +/- ##
==========================================
+ Coverage 77.76% 77.95% +0.19%
==========================================
Files 1650 1650
Lines 92338 97418 +5080
Branches 31959 33442 +1483
==========================================
+ Hits 71805 75947 +4142
- Misses 19865 20760 +895
- Partials 668 711 +43
Flags with carried forward coverage won't be shown. Click here to find out more.
... and 133 files with indirect coverage changes 🚀 New features to boost your workflow:
|
There was a problem hiding this comment.
🔍 Cursor Review — Consolidated panel
Triggered by @MaanilVerma.
Found 6 finding(s).
| Severity | Count |
|---|---|
| 🟠 High | 1 |
| 🟡 Medium | 2 |
| 🟢 Low | 2 |
| ⚪ Nit | 1 |
Panel: 8/8 reviewers contributed findings.
There was a problem hiding this comment.
Actionable comments posted: 1
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
src/platform/cloud/onboarding/survey/DynamicSurveyForm.vue (1)
212-224: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win"Other" required-field validation ignores multi-select values.
value === 'other'only matches scalar values. For amultifield withallowOther,valueis an array, so this check never triggers and the function falls through toreturn true, letting the user advance/submit while 'other' is selected but the required free-text is empty.DynamicSurveyField.vue'sisOtherSelectedalready handles this correctly by checkingArray.isArray(modelValue) ? modelValue.includes('other') : modelValue === 'other', confirming multi+other is a supported combination that this validity check misses.🐛 Proposed fix
- if (field.allowOther && field.otherFieldId && value === 'other') { + const selectedOther = Array.isArray(value) + ? value.includes('other') + : value === 'other' + if (field.allowOther && field.otherFieldId && selectedOther) { const other = values[field.otherFieldId] return typeof other === 'string' && other.trim().length > 0 }Also worth adding a
multi+allowOthertest case toDynamicSurveyForm.test.tsto cover this path going forward.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/platform/cloud/onboarding/survey/DynamicSurveyForm.vue` around lines 212 - 224, The validation in DynamicSurveyForm.vue’s isCurrentValid only checks value === 'other', so it misses the multi-select + allowOther case where the value is an array and the required free-text can be bypassed. Update the check to detect "other" for both scalar and array values, consistent with DynamicSurveyField.vue’s isOtherSelected logic, and then require the otherFieldId text when present. Add or update a DynamicSurveyForm.test.ts case covering multi plus allowOther to verify the free-text is enforced before advancing.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@src/platform/cloud/onboarding/survey/DynamicSurveyForm.vue`:
- Around line 40-47: The inline event handlers in DynamicSurveyForm.vue are
calling the async onFieldChange function without handling its returned promise,
which violates the floating-promises guideline. Update the `@update`:model-value
and `@update`:other-value handlers to explicitly handle the promise, either by
awaiting the call in an async handler or by intentionally voiding it. Use the
onFieldChange helper and the currentField.id/currentField.otherFieldId wiring as
the place to fix this.
---
Outside diff comments:
In `@src/platform/cloud/onboarding/survey/DynamicSurveyForm.vue`:
- Around line 212-224: The validation in DynamicSurveyForm.vue’s isCurrentValid
only checks value === 'other', so it misses the multi-select + allowOther case
where the value is an array and the required free-text can be bypassed. Update
the check to detect "other" for both scalar and array values, consistent with
DynamicSurveyField.vue’s isOtherSelected logic, and then require the
otherFieldId text when present. Add or update a DynamicSurveyForm.test.ts case
covering multi plus allowOther to verify the free-text is enforced before
advancing.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro Plus
Run ID: a398a5ca-9968-49a5-864f-953d96c92405
📒 Files selected for processing (14)
src/locales/en/main.jsonsrc/platform/cloud/onboarding/CloudSurveyView.vuesrc/platform/cloud/onboarding/components/CloudTemplate.vuesrc/platform/cloud/onboarding/components/CloudTemplateFooter.vuesrc/platform/cloud/onboarding/onboardingCloudRoutes.tssrc/platform/cloud/onboarding/survey/DynamicSurveyField.test.tssrc/platform/cloud/onboarding/survey/DynamicSurveyField.vuesrc/platform/cloud/onboarding/survey/DynamicSurveyForm.test.tssrc/platform/cloud/onboarding/survey/DynamicSurveyForm.vuesrc/platform/cloud/onboarding/survey/defaultSurveySchema.tssrc/platform/cloud/onboarding/survey/surveySchema.test.tssrc/platform/cloud/onboarding/survey/surveySchema.tssrc/platform/remoteConfig/types.tssrc/platform/telemetry/types.ts
- Stop auto-advancing on a cleared single-select and re-clamp stepIndex so a backend showWhen that hides an earlier field can't strand an empty step - Detect "other" for multi-select too across validity, schema, and payload, and reject whitespace-only free-text
…Comfy-Org/ComfyUI_frontend into feat/onboarding-survey-redesign
Summary
New users get a cleaner, faster onboarding survey: one question per screen on tappable cards that advance the moment you pick an answer, with follow-up questions that appear only when they're relevant. The questions themselves were reworked to learn what people actually want to do with ComfyUI.
Changes
What
Breaking — None. The remote-config survey schema stays backend-overridable, hidden branch answers are zeroed in the submitted payload, and the telemetry field names line up 1:1 with the schema. The backend dynamic config already ships the matching version-3 schema.
Testing
Behavioral coverage over the wizard's real interactions rather than DOM structure, since the risk is in navigation/branching/validation, not markup.
vue-i18nis mounted for real with the actual locale file so tests assert on rendered copy.hasNonEmptyValuetruth table.Gates:
vue-tsctypecheck clean; eslint/oxfmt clean on touched files; survey suite green (68 tests across the three files). Manual: run the cloud onboarding flow, pick a workflow/apps intent to confirm the "building" follow-up, pick social to confirm the platform follow-up, and verify an empty "other" blocks advancing.Screen Recording
Screen.Recording.2026-07-08.at.9.51.19.PM.mov