Skip to content

Conversation

@christian-byrne
Copy link
Contributor

@christian-byrne christian-byrne commented Oct 26, 2025

Summary

Migrated help center and release notification components from hardcoded colors to semantic design tokens for automatic light/dark theme support.

Selection_2298 Selection_2265 Screenshot from 2025-10-25 21-46-11 Screenshot from 2025-10-25 21-46-25

Changes

  • What: Replaced hardcoded hex/rgb colors with semantic tokens in HelpCenterMenuContent, WhatsNewPopup, and ReleaseNotificationToast components
  • Design System: Added --interface-menu-surface and --interface-menu-stroke tokens to style.css for consistent menu theming
  • UX: Updated help center menu structure - added "Give Feedback" button, renamed "Help & Feedback" to "Help & Support", switched to Lucide icons (except Discord brand logo), added external-link icons

┆Issue is synchronized with this Notion page by Unito

@dosubot dosubot bot added the size:L This PR changes 100-499 lines, ignoring generated files. label Oct 26, 2025
@github-actions
Copy link

github-actions bot commented Oct 26, 2025

🎨 Storybook Build Status

Build completed successfully!

⏰ Completed at: 11/28/2025, 07:24:29 PM UTC

🔗 Links


🎉 Your Storybook is ready for review!

@github-actions
Copy link

github-actions bot commented Oct 26, 2025

🎭 Playwright Test Results

⚠️ Tests passed with flaky tests

⏰ Completed at: 11/28/2025, 07:33:05 PM UTC

📈 Summary

  • Total Tests: 493
  • Passed: 479 ✅
  • Failed: 0
  • Flaky: 5 ⚠️
  • Skipped: 9 ⏭️

📊 Test Reports by Browser

  • chromium: View Report • ✅ 470 / ❌ 0 / ⚠️ 5 / ⏭️ 9
  • 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 Oct 26, 2025

Bundle Size Report

Summary

  • Raw size: 17 MB baseline 17 MB — 🔴 +3.63 kB
  • Gzip: 3.37 MB baseline 3.37 MB — 🔴 +590 B
  • Brotli: 2.58 MB baseline 2.58 MB — 🔴 +217 B
  • Bundles: 97 current • 97 baseline • 36 added / 36 removed

Category Glance
Graph Workspace 🔴 +3.38 kB (952 kB) · App Entry Points 🔴 +247 B (3.18 MB) · Vendor & Third-Party ⚪ 0 B (8.56 MB) · Other ⚪ 0 B (3.84 MB) · Panels & Settings ⚪ 0 B (298 kB) · UI Components ⚪ 0 B (139 kB) · + 3 more

Per-category breakdown
App Entry Points — 3.18 MB (baseline 3.18 MB) • 🔴 +247 B

Main entry bundles and manifests

File Before After Δ Raw Δ Gzip Δ Brotli
assets/index-DPsqcOWI.js (new) 2.95 MB 🔴 +2.95 MB 🔴 +616 kB 🔴 +467 kB
assets/index-BaIAwWq_.js (removed) 2.95 MB 🟢 -2.95 MB 🟢 -615 kB 🟢 -467 kB
assets/index-CwfkVyor.js (removed) 227 kB 🟢 -227 kB 🟢 -48.6 kB 🟢 -40 kB
assets/index-DDPuIrOe.js (new) 227 kB 🔴 +227 kB 🔴 +48.6 kB 🔴 +40 kB
assets/index-eKNCL0OB.js (new) 345 B 🔴 +345 B 🔴 +244 B 🔴 +237 B
assets/index-i47K8MSK.js (removed) 345 B 🟢 -345 B 🟢 -247 B 🟢 -202 B

Status: 3 added / 3 removed

Graph Workspace — 952 kB (baseline 949 kB) • 🔴 +3.38 kB

Graph editor runtime, canvas, workflow orchestration

File Before After Δ Raw Δ Gzip Δ Brotli
assets/GraphView-9EModXLq.js (new) 952 kB 🔴 +952 kB 🔴 +184 kB 🔴 +141 kB
assets/GraphView-S1JZi48B.js (removed) 949 kB 🟢 -949 kB 🟢 -184 kB 🟢 -141 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-B0E0nQXr.js (removed) 6.54 kB 🟢 -6.54 kB 🟢 -2.14 kB 🟢 -1.9 kB
assets/UserSelectView-DARjqdE0.js (new) 6.54 kB 🔴 +6.54 kB 🔴 +2.14 kB 🔴 +1.9 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-BN2AtoPv.js (new) 21.4 kB 🔴 +21.4 kB 🔴 +5.15 kB 🔴 +4.5 kB
assets/CreditsPanel-FOG1Bfds.js (removed) 21.4 kB 🟢 -21.4 kB 🟢 -5.15 kB 🟢 -4.5 kB
assets/KeybindingPanel-BvUW9OBA.js (new) 13.6 kB 🔴 +13.6 kB 🔴 +3.42 kB 🔴 +3.01 kB
assets/KeybindingPanel-ChJAkqX7.js (removed) 13.6 kB 🟢 -13.6 kB 🟢 -3.42 kB 🟢 -3.01 kB
assets/ExtensionPanel-CJ6MAKHf.js (removed) 10.8 kB 🟢 -10.8 kB 🟢 -2.57 kB 🟢 -2.25 kB
assets/ExtensionPanel-Crg-TOII.js (new) 10.8 kB 🔴 +10.8 kB 🔴 +2.57 kB 🔴 +2.25 kB
assets/AboutPanel-CdxJ9jbb.js (new) 9.16 kB 🔴 +9.16 kB 🔴 +2.46 kB 🔴 +2.21 kB
assets/AboutPanel-CZ6vni3M.js (removed) 9.16 kB 🟢 -9.16 kB 🟢 -2.46 kB 🟢 -2.21 kB
assets/ServerConfigPanel-7YdA7IjW.js (removed) 6.56 kB 🟢 -6.56 kB 🟢 -1.83 kB 🟢 -1.62 kB
assets/ServerConfigPanel-gih8-IXf.js (new) 6.56 kB 🔴 +6.56 kB 🔴 +1.83 kB 🔴 +1.62 kB
assets/UserPanel-ByIMnEz0.js (removed) 6.23 kB 🟢 -6.23 kB 🟢 -1.72 kB 🟢 -1.52 kB
assets/UserPanel-Cm7nlXj9.js (new) 6.23 kB 🔴 +6.23 kB 🔴 +1.72 kB 🔴 +1.5 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 — 139 kB (baseline 139 kB) • ⚪ 0 B

Reusable component library chunks

File Before After Δ Raw Δ Gzip Δ Brotli
assets/Load3D.vue_vue_type_script_setup_true_lang-BuQPaoP9.js (new) 53.9 kB 🔴 +53.9 kB 🔴 +8.52 kB 🔴 +7.31 kB
assets/Load3D.vue_vue_type_script_setup_true_lang-DSWOEFJB.js (removed) 53.9 kB 🟢 -53.9 kB 🟢 -8.52 kB 🟢 -7.31 kB
assets/WidgetSelect.vue_vue_type_script_setup_true_lang-CcjBh-bG.js (new) 47 kB 🔴 +47 kB 🔴 +10.1 kB 🔴 +8.78 kB
assets/WidgetSelect.vue_vue_type_script_setup_true_lang-DUwIwQBq.js (removed) 47 kB 🟢 -47 kB 🟢 -10.1 kB 🟢 -8.78 kB
assets/WidgetInputNumber.vue_vue_type_script_setup_true_lang-akAeHUog.js (removed) 12.8 kB 🟢 -12.8 kB 🟢 -3.35 kB 🟢 -2.96 kB
assets/WidgetInputNumber.vue_vue_type_script_setup_true_lang-DN9lWcLe.js (new) 12.8 kB 🔴 +12.8 kB 🔴 +3.35 kB 🔴 +2.95 kB
assets/ComfyQueueButton-CIzFa9z8.js (removed) 8.44 kB 🟢 -8.44 kB 🟢 -2.48 kB 🟢 -2.21 kB
assets/ComfyQueueButton-Cx2STPuo.js (new) 8.44 kB 🔴 +8.44 kB 🔴 +2.48 kB 🔴 +2.21 kB
assets/MediaTitle.vue_vue_type_script_setup_true_lang-CtAMGEIT.js (removed) 897 B 🟢 -897 B 🟢 -504 B 🟢 -429 B
assets/MediaTitle.vue_vue_type_script_setup_true_lang-SFfZQkXl.js (new) 897 B 🔴 +897 B 🔴 +504 B 🔴 +432 B
assets/LazyImage.vue_vue_type_script_setup_true_lang-Pm3jgX4e.js 10.8 kB 10.8 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/UserAvatar.vue_vue_type_script_setup_true_lang-Bs-EIQeq.js 1.34 kB 1.34 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/WidgetButton-CsMa_P26.js 2.04 kB 2.04 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/WidgetLayoutField.vue_vue_type_script_setup_true_lang-Cf8dNyi2.js 2 kB 2 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B

Status: 5 added / 5 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-CchRYcle.js (removed) 7.51 kB 🟢 -7.51 kB 🟢 -1.83 kB 🟢 -1.58 kB
assets/keybindingService-DU0KKGHU.js (new) 7.51 kB 🔴 +7.51 kB 🔴 +1.83 kB 🔴 +1.58 kB
assets/audioService-BiMPzf0O.js (removed) 2.2 kB 🟢 -2.2 kB 🟢 -959 B 🟢 -823 B
assets/audioService-CwcvWPer.js (new) 2.2 kB 🔴 +2.2 kB 🔴 +958 B 🔴 +821 B
assets/serverConfigStore-B5NW8oSr.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-Bw6F1MDV.js (removed) 1.41 kB 🟢 -1.41 kB 🟢 -652 B 🟢 -550 B
assets/audioUtils-DqCQfjOg.js (new) 1.41 kB 🔴 +1.41 kB 🔴 +650 B 🔴 +541 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-uhYFfslB.js 452 kB 452 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/vendor-other-DisjWJFj.js 3.98 MB 3.98 MB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/vendor-primevue-LncEKxae.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-C4yk8cCR.js 232 kB 232 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/vendor-vue-tw3tq7KH.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.84 MB (baseline 3.84 MB) • ⚪ 0 B

Bundles that do not match a named category

File Before After Δ Raw Δ Gzip Δ Brotli
assets/WidgetRecordAudio-_BGPiv3A.js (removed) 20.4 kB 🟢 -20.4 kB 🟢 -5.24 kB 🟢 -4.64 kB
assets/WidgetRecordAudio-6NS4lnf4.js (new) 20.4 kB 🔴 +20.4 kB 🔴 +5.24 kB 🔴 +4.63 kB
assets/AudioPreviewPlayer-DF7QB_MQ.js (removed) 13.5 kB 🟢 -13.5 kB 🟢 -3.4 kB 🟢 -3.04 kB
assets/AudioPreviewPlayer-Djv51hsA.js (new) 13.5 kB 🔴 +13.5 kB 🔴 +3.4 kB 🔴 +3.04 kB
assets/WidgetGalleria-BSYddw6E.js (new) 4.1 kB 🔴 +4.1 kB 🔴 +1.45 kB 🔴 +1.3 kB
assets/WidgetGalleria-wxuh6lR8.js (removed) 4.1 kB 🟢 -4.1 kB 🟢 -1.45 kB 🟢 -1.3 kB
assets/WidgetColorPicker-CJpdHTbO.js (removed) 3.41 kB 🟢 -3.41 kB 🟢 -1.38 kB 🟢 -1.23 kB
assets/WidgetColorPicker-D8WlnTOi.js (new) 3.41 kB 🔴 +3.41 kB 🔴 +1.38 kB 🔴 +1.23 kB
assets/WidgetMarkdown-CogTxGU4.js (new) 3.1 kB 🔴 +3.1 kB 🔴 +1.29 kB 🔴 +1.13 kB
assets/WidgetMarkdown-D4PNapCQ.js (removed) 3.1 kB 🟢 -3.1 kB 🟢 -1.29 kB 🟢 -1.13 kB
assets/WidgetAudioUI-BpmJnqFZ.js (removed) 2.82 kB 🟢 -2.82 kB 🟢 -1.12 kB 🟢 -1.02 kB
assets/WidgetAudioUI-CL34v_ud.js (new) 2.82 kB 🔴 +2.82 kB 🔴 +1.12 kB 🔴 +1.02 kB
assets/WidgetTextarea-BmuXSLjd.js (removed) 2.48 kB 🟢 -2.48 kB 🟢 -1.01 kB 🟢 -900 B
assets/WidgetTextarea-C9ntY8ny.js (new) 2.48 kB 🔴 +2.48 kB 🔴 +1.01 kB 🔴 +902 B
assets/WidgetInputText-38kZaJIb.js (new) 1.99 kB 🔴 +1.99 kB 🔴 +918 B 🔴 +849 B
assets/WidgetInputText-Dd1116ep.js (removed) 1.99 kB 🟢 -1.99 kB 🟢 -918 B 🟢 -845 B
assets/MediaImageBottom-Dze5Q59G.js (removed) 1.57 kB 🟢 -1.57 kB 🟢 -741 B 🟢 -642 B
assets/MediaImageBottom-DzsBZ4lg.js (new) 1.57 kB 🔴 +1.57 kB 🔴 +745 B 🔴 +643 B
assets/MediaAudioBottom-BsJzqsRi.js (new) 1.52 kB 🔴 +1.52 kB 🔴 +742 B 🔴 +654 B
assets/MediaAudioBottom-DK6LbcyF.js (removed) 1.52 kB 🟢 -1.52 kB 🟢 -743 B 🟢 -654 B
assets/MediaVideoBottom-Dsi-aqzB.js (new) 1.52 kB 🔴 +1.52 kB 🔴 +740 B 🔴 +653 B
assets/MediaVideoBottom-psm2uv7r.js (removed) 1.52 kB 🟢 -1.52 kB 🟢 -738 B 🟢 -652 B
assets/Media3DBottom-BkDMe23u.js (new) 1.5 kB 🔴 +1.5 kB 🔴 +733 B 🔴 +649 B
assets/Media3DBottom-BwqtZQoo.js (removed) 1.5 kB 🟢 -1.5 kB 🟢 -732 B 🟢 -649 B
assets/Media3DTop-D2IaaD1x.js (removed) 1.49 kB 🟢 -1.49 kB 🟢 -765 B 🟢 -649 B
assets/Media3DTop-Dy20IgiU.js (new) 1.49 kB 🔴 +1.49 kB 🔴 +766 B 🔴 +651 B
assets/WidgetSelect-C7zIioLp.js (removed) 655 B 🟢 -655 B 🟢 -343 B 🟢 -306 B
assets/WidgetSelect-CzBu_Sro.js (new) 655 B 🔴 +655 B 🔴 +342 B 🔴 +288 B
assets/WidgetInputNumber-CjetyY7o.js (new) 595 B 🔴 +595 B 🔴 +328 B 🔴 +275 B
assets/WidgetInputNumber-lBYQz7IE.js (removed) 595 B 🟢 -595 B 🟢 -330 B 🟢 -276 B
assets/Load3D-CDK7qIaS.js (removed) 424 B 🟢 -424 B 🟢 -269 B 🟢 -224 B
assets/Load3D-DgTfCCzX.js (new) 424 B 🔴 +424 B 🔴 +266 B 🔴 +223 B
assets/WidgetLegacy-B9V2d40_.js (removed) 364 B 🟢 -364 B 🟢 -236 B 🟢 -195 B
assets/WidgetLegacy-CNr0cVtM.js (new) 364 B 🔴 +364 B 🔴 +237 B 🔴 +193 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-5lOBdqcC.js 84.5 kB 84.5 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/main-BOCuaVpE.js 73.4 kB 73.4 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/main-ClrEFGUz.js 72.4 kB 72.4 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/main-Cw9RZWRY.js 89 B 89 B ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/main-CyNU0iQX.js 99.3 kB 99.3 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/main-D7gwLxft.js 114 kB 114 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/main-DC8o4BCt.js 86.8 kB 86.8 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/main-DKiesCV4.js 94.3 kB 94.3 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/main-Hq2q-OtB.js 83.6 kB 83.6 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/main-USAlAlnj.js 82 kB 82 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/MediaAudioTop-Bqc4HR5L.js 1.46 kB 1.46 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/MediaImageTop-DbyT2UjV.js 1.75 kB 1.75 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/MediaVideoTop-6PQqfKb3.js 2.76 kB 2.76 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/nodeDefs-_Px5dSNW.js 306 kB 306 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/nodeDefs-7z21KPoS.js 285 kB 285 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/nodeDefs-Bw_Jitw_.js 101 B 101 B ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/nodeDefs-BWKZzBPK.js 346 kB 346 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/nodeDefs-CGbgH4Yl.js 320 kB 320 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/nodeDefs-CjjjdWkV.js 313 kB 313 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/nodeDefs-CVrNtxvj.js 288 kB 288 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/nodeDefs-DLRSA0IK.js 309 kB 309 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/nodeDefs-DQV2gnwA.js 372 kB 372 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/nodeDefs-ofqLG5vz.js 310 kB 310 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/WidgetChart-C9sMH5oS.js 2.48 kB 2.48 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/WidgetImageCompare-D4gTOuOo.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
assets/WidgetToggleSwitch-CBRsIck7.js 1.58 kB 1.58 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B

Status: 17 added / 17 removed

@christian-byrne christian-byrne added claude-review Add to trigger a PR code review from Claude Code and removed claude-review Add to trigger a PR code review from Claude Code labels Oct 26, 2025
claude[bot]

This comment was marked as outdated.

@github-actions github-actions bot removed the claude-review Add to trigger a PR code review from Claude Code label Oct 27, 2025
@christian-byrne christian-byrne marked this pull request as draft November 3, 2025 00:38
@christian-byrne christian-byrne force-pushed the style/whatsnew-light-mode branch from d9eef91 to f62a5e4 Compare November 7, 2025 04:28
@christian-byrne christian-byrne marked this pull request as ready for review November 13, 2025 18:14
@dosubot dosubot bot added size:XXL This PR changes 1000+ lines, ignoring generated files. and removed size:L This PR changes 100-499 lines, ignoring generated files. labels Nov 13, 2025
@christian-byrne christian-byrne force-pushed the style/whatsnew-light-mode branch from 467de81 to e7a6eae Compare November 27, 2025 01:05
@christian-byrne christian-byrne requested a review from a team as a code owner November 27, 2025 01:05
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Nov 27, 2025

Note

Other AI code review bot(s) detected

CodeRabbit has detected other AI code review bot(s) in this pull request and will avoid duplicating their findings in the review comments. This may lead to a less comprehensive review.

📝 Walkthrough

Walkthrough

Reworks Help Center menu and release UIs (toast and Whats New popup), adds interface-menu CSS tokens, updates localization, replaces a CSS test selector with a data-testid, adds Storybook stories and unit tests, and deletes an obsolete WhatsNewPopup test file.

Changes

Cohort / File(s) Summary
CSS Design Tokens
packages/design-system/src/css/style.css
Added --interface-menu-surface and --interface-menu-stroke custom properties plus public aliases --color-interface-menu-surface / --color-interface-menu-stroke, applied in light/dark theme mappings.
Test Selector Update
browser_tests/tests/releaseNotifications.spec.ts
Replaced .whats-new-section CSS locator with getByTestId('whats-new-section') throughout the test file.
Help Center Menu
src/components/helpcenter/HelpCenterMenuContent.vue
Reworked layout to full-width flex wrapper; added top-level feedback/help items; per-item showExternalIcon and updated icons/spacing; adjusted Whats New markup; removed legacy update button and extended MenuItem with showExternalIcon?: boolean.
Release Notification Toast
src/platform/updates/components/ReleaseNotificationToast.vue, src/platform/updates/components/ReleaseNotificationToast.stories.ts, src/platform/updates/components/ReleaseNotificationToast.test.ts
Redesigned toast as card with rocket icon, two-line header, markdown-stripped description, footer actions; added formattedContent logic; exposed methods handleSkip, handleLearnMore, handleUpdate; added Storybook stories and unit tests.
What's New Popup
src/platform/updates/components/WhatsNewPopup.vue, src/platform/updates/components/WhatsNewPopup.stories.ts, src/platform/updates/components/WhatsNewPopup.test.ts
Converted popup to modal header/body/footer; added image extraction and image-first rendering, markdown rendering with fallbacks, CTA handler that opens docs and closes popup; exposed methods show, hide, handleCTA, closePopup; added stories and tests.
Localization Strings
src/locales/en/main.json
Added helpCenter.feedback; renamed helpCenter.helpFeedbackhelpCenter.help; updated releaseToast texts and added releaseToast.description; added whatsNewPopup.later / whatsNewPopup.update and new helpCenterMenu / recentReleases keys.
Removed Test Suite
tests-ui/tests/components/helpcenter/WhatsNewPopup.test.ts
Deleted legacy WhatsNewPopup test file and its test cases and mocks.

Possibly related PRs

✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch style/whatsnew-light-mode

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

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 (2)
src/platform/updates/components/ReleaseNotificationToast.vue (1)

133-148: Add timer cleanup on component unmount.

The auto-hide timer is cleared when shouldShow becomes false, but there's no cleanup if the component unmounts while the timer is active. This could cause a memory leak or attempt to update unmounted component state.

Add cleanup in an onUnmounted hook:

+import { computed, onMounted, onUnmounted, ref, watch } from 'vue'

// ... existing code ...

+onUnmounted(() => {
+  clearAutoHide()
+})
src/components/helpcenter/HelpCenterMenuContent.vue (1)

524-529: Remove unused onUpdate function to fix CI failure.

The onUpdate function is declared but never used, causing the TypeScript build to fail (TS6133). This blocks the CI pipeline.

-const onUpdate = (_: ReleaseNote): void => {
-  openExternalLink(
-    buildDocsUrl('/installation/update_comfyui', { includeLocale: true })
-  )
-  emit('close')
-}
♻️ Duplicate comments (1)
src/platform/updates/components/WhatsNewPopup.vue (1)

15-19: Verify HTML sanitization for v-html usage.

Similar to the toast component, this uses v-html for rendering markdown content. The same sanitization verification applies.

🧹 Nitpick comments (6)
src/platform/updates/components/ReleaseNotificationToast.test.ts (2)

51-75: Consider extracting shared mock translations to reduce duplication.

The translation map is duplicated in vi.mock('vue-i18n') (lines 9-24) and mountComponent (lines 55-65). Extract to a shared constant for maintainability:

+const mockTranslations: Record<string, string> = {
+  'releaseToast.newVersionAvailable': 'New update is out!',
+  'releaseToast.whatsNew': "See what's new",
+  'releaseToast.skip': 'Skip',
+  'releaseToast.update': 'Update',
+  'releaseToast.description':
+    'Check out the latest improvements and features in this update.'
+}
+
 vi.mock('vue-i18n', () => ({
   useI18n: vi.fn(() => ({
     locale: { value: 'en' },
-    t: vi.fn((key: string) => {
-      const translations: Record<string, string> = {
-        'releaseToast.newVersionAvailable': 'New update is out!',
-        ...
-      }
-      return translations[key] || key
-    })
+    t: vi.fn((key: string) => mockTranslations[key] || key)
   }))
 }))

220-243: Timer test assertion may be flaky.

The test expects vi.getTimerCount() to be 0 after auto-hide triggers, but this depends on the component's internal implementation clearing the timer. If the component uses clearTimeout on unmount rather than after the callback executes, this assertion could fail.

Consider also verifying the expected behavior (e.g., that a dismiss function was called) rather than relying solely on timer count:

     // Fast-forward time to trigger auto-hide
     vi.advanceTimersByTime(8000)
     await wrapper.vm.$nextTick()
 
-    // Component should call dismissToast internally which hides it
-    // We can't test DOM visibility change because the component uses local state
-    // But we can verify the timer was set and would have triggered
-    expect(vi.getTimerCount()).toBe(0) // Timer should be cleared after auto-hide
+    // Verify the component's dismiss behavior was triggered
+    // The specific assertion depends on component implementation
src/platform/updates/components/WhatsNewPopup.test.ts (1)

10-41: Same duplication pattern as ReleaseNotificationToast.test.ts.

The translation mocks are duplicated in three places: vi.mock('@/i18n'), vi.mock('vue-i18n'), and mountComponent. Consider extracting to a shared constant or even a shared test utility for the platform/updates components.

Also applies to: 67-92

src/platform/updates/components/ReleaseNotificationToast.stories.ts (1)

8-67: Consider extracting shared mock data to a separate fixture file.

The mockReleases array is duplicated in both ReleaseNotificationToast.stories.ts and WhatsNewPopup.stories.ts. This could lead to maintenance issues if the mock data needs to be updated.

Consider creating a shared fixtures file:

// src/platform/updates/components/__fixtures__/mockReleases.ts
export const mockReleases: ReleaseNote[] = [/* ... */]

Then import it in both story files.

src/components/helpcenter/HelpCenterMenuContent.vue (2)

34-43: Use Tailwind utilities instead of inline styles.

As noted in a previous review, inline styles should be replaced with Tailwind utility classes for consistency.

          <i
            v-if="menuItem.showExternalIcon"
-           class="icon-[lucide--external-link] text-primary"
-           style="width: 16px; height: 16px; margin-left: auto"
+           class="icon-[lucide--external-link] text-primary w-4 h-4 ml-auto"
          />
          <i
            v-if="menuItem.key === 'more'"
-           class="pi pi-chevron-right"
-           style="margin-left: auto"
+           class="pi pi-chevron-right ml-auto"
          />

539-550: Extensive custom CSS in src/components.

The coding guidelines indicate src/components/**/*.{vue,css} should use "Tailwind CSS only for styling (no custom CSS)". While the CSS here is well-structured with semantic design tokens, it's quite extensive. Consider whether this could be migrated to Tailwind utilities in a future refactor.

This is a larger refactoring effort and can be addressed in a follow-up PR if desired.

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

🧹 Nitpick comments (2)
src/components/helpcenter/HelpCenterMenuContent.vue (1)

34-43: Replace inline styles with Tailwind utility classes.

The external link and chevron icons use inline styles that can be replaced with Tailwind classes for better consistency and maintainability.

Apply this diff:

           <i
             v-if="menuItem.showExternalIcon"
             class="icon-[lucide--external-link] text-primary"
-            style="width: 16px; height: 16px; margin-left: auto"
+            class="ml-auto h-4 w-4"
           />
           <i
             v-if="menuItem.key === 'more'"
             class="pi pi-chevron-right"
-            style="margin-left: auto"
+            class="ml-auto"
           />

As per coding guidelines and past review feedback, prefer Tailwind utility classes over inline styles.

src/platform/updates/components/WhatsNewPopup.vue (1)

165-170: Consider limiting defineExpose to essential imperative operations.

According to coding guidelines, defineExpose should be used "only for imperative operations (such as form.validate(), modal.open())". While show and hide are appropriate for imperative modal control, exposing handleCTA and closePopup may be unnecessary unless required for testing purposes.

Based on learnings: Use defineExpose only for imperative operations (such as form.validate(), modal.open()).

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between e7a6eae and f3364e7.

📒 Files selected for processing (3)
  • src/components/helpcenter/HelpCenterMenuContent.vue (13 hunks)
  • src/locales/en/main.json (4 hunks)
  • src/platform/updates/components/WhatsNewPopup.vue (7 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/locales/en/main.json
🧰 Additional context used
📓 Path-based instructions (15)
**/*.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/components/helpcenter/HelpCenterMenuContent.vue
  • src/platform/updates/components/WhatsNewPopup.vue
**/*.{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/components/helpcenter/HelpCenterMenuContent.vue
  • src/platform/updates/components/WhatsNewPopup.vue
**/*.{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/components/helpcenter/HelpCenterMenuContent.vue
  • src/platform/updates/components/WhatsNewPopup.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/components/helpcenter/HelpCenterMenuContent.vue
  • src/platform/updates/components/WhatsNewPopup.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/components/helpcenter/HelpCenterMenuContent.vue
  • src/platform/updates/components/WhatsNewPopup.vue
**/*.{ts,tsx,js,jsx,vue}

📄 CodeRabbit inference engine (CLAUDE.md)

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

Files:

  • src/components/helpcenter/HelpCenterMenuContent.vue
  • src/platform/updates/components/WhatsNewPopup.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/components/helpcenter/HelpCenterMenuContent.vue
  • src/platform/updates/components/WhatsNewPopup.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:

  • src/components/helpcenter/HelpCenterMenuContent.vue
  • src/platform/updates/components/WhatsNewPopup.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/components/helpcenter/HelpCenterMenuContent.vue
  • src/platform/updates/components/WhatsNewPopup.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/components/helpcenter/HelpCenterMenuContent.vue
  • src/platform/updates/components/WhatsNewPopup.vue
src/**/*.{vue,ts,tsx}

📄 CodeRabbit inference engine (src/CLAUDE.md)

Follow Vue 3 composition API style guide

Files:

  • src/components/helpcenter/HelpCenterMenuContent.vue
  • src/platform/updates/components/WhatsNewPopup.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/components/helpcenter/HelpCenterMenuContent.vue
  • src/platform/updates/components/WhatsNewPopup.vue
src/components/**/*.vue

📄 CodeRabbit inference engine (src/components/CLAUDE.md)

src/components/**/*.vue: Use setup() function in Vue 3 Composition API
Destructure props using Vue 3.5 style in Vue components
Use ref/reactive for state management in Vue 3 Composition API
Implement computed() for derived state in Vue 3 Composition API
Use provide/inject for dependency injection in Vue components
Prefer emit/@event-name for state changes over other communication patterns
Use defineExpose only for imperative operations (such as form.validate(), modal.open())
Replace PrimeVue Dropdown component with Select
Replace PrimeVue OverlayPanel component with Popover
Replace PrimeVue Calendar component with DatePicker
Replace PrimeVue InputSwitch component with ToggleSwitch
Replace PrimeVue Sidebar component with Drawer
Replace PrimeVue Chips component with AutoComplete with multiple enabled
Replace PrimeVue TabMenu component with Tabs without panels
Replace PrimeVue Steps component with Stepper without panels
Replace PrimeVue InlineMessage component with Message
Extract complex conditionals to computed properties
Implement cleanup for async operations in Vue components
Use lifecycle hooks: onMounted, onUpdated in Vue 3 Composition API
Use Teleport/Suspense when needed for component rendering
Define proper props and emits definitions in Vue components

Files:

  • src/components/helpcenter/HelpCenterMenuContent.vue
src/components/**/*.{vue,css}

📄 CodeRabbit inference engine (src/components/CLAUDE.md)

src/components/**/*.{vue,css}: Use Tailwind CSS only for styling (no custom CSS)
Use the correct tokens from style.css in the design system package

Files:

  • src/components/helpcenter/HelpCenterMenuContent.vue
src/components/**/*.{vue,ts,js}

📄 CodeRabbit inference engine (src/components/CLAUDE.md)

src/components/**/*.{vue,ts,js}: Use existing VueUse composables (such as useElementHover) instead of manually managing event listeners
Use useIntersectionObserver for visibility detection instead of custom scroll handlers
Use vue-i18n for ALL UI strings

Files:

  • src/components/helpcenter/HelpCenterMenuContent.vue
🧠 Learnings (27)
📓 Common learnings
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-11-24T19:48:23.088Z
Learning: Pull requests must include a clear description, linked issues in the format `- Fixes #123`, and screenshots/GIFs for UI changes
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
📚 Learning: 2025-11-24T19:47:34.324Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:34.324Z
Learning: Applies to src/**/*.{ts,tsx,vue} : Sanitize HTML with DOMPurify to prevent XSS attacks

Applied to files:

  • src/components/helpcenter/HelpCenterMenuContent.vue
📚 Learning: 2025-11-24T19:47:14.779Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:14.779Z
Learning: Applies to **/*.vue : Never use `:class="[]"` to merge class names - always use `import { cn } from '@/utils/tailwindUtil'` for class merging in Vue templates

Applied to files:

  • src/components/helpcenter/HelpCenterMenuContent.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 : Use Tailwind CSS for styling

Applied to files:

  • src/components/helpcenter/HelpCenterMenuContent.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 Tailwind CSS for styling Vue components

Applied to files:

  • src/components/helpcenter/HelpCenterMenuContent.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 responsive design with Tailwind CSS

Applied to files:

  • src/components/helpcenter/HelpCenterMenuContent.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,css} : Use Tailwind CSS only for styling (no custom CSS)

Applied to files:

  • src/components/helpcenter/HelpCenterMenuContent.vue
📚 Learning: 2025-11-24T19:47:34.324Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:34.324Z
Learning: Applies to src/**/{components,composables}/**/*.{ts,tsx,vue} : Use vue-i18n for ALL user-facing strings by adding them to `src/locales/en/main.json`

Applied to files:

  • src/components/helpcenter/HelpCenterMenuContent.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,ts,js} : Use vue-i18n for ALL UI strings

Applied to files:

  • src/components/helpcenter/HelpCenterMenuContent.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} : Use vue-i18n in Composition API for any string literals and place new translation entries in src/locales/en/main.json

Applied to files:

  • src/components/helpcenter/HelpCenterMenuContent.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,ts} : Use vue-i18n in composition API for any string literals. Place new translation entries in src/locales/en/main.json

Applied to files:

  • src/components/helpcenter/HelpCenterMenuContent.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 TabMenu component with Tabs without panels

Applied to files:

  • src/components/helpcenter/HelpCenterMenuContent.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/components/helpcenter/HelpCenterMenuContent.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/components/helpcenter/HelpCenterMenuContent.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 lifecycle hooks: onMounted, onUpdated in Vue 3 Composition API

Applied to files:

  • src/components/helpcenter/HelpCenterMenuContent.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 InputSwitch component with ToggleSwitch

Applied to files:

  • src/components/helpcenter/HelpCenterMenuContent.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 InlineMessage component with Message

Applied to files:

  • src/components/helpcenter/HelpCenterMenuContent.vue
  • src/platform/updates/components/WhatsNewPopup.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 ref/reactive for state management in Vue 3 Composition API

Applied to files:

  • src/components/helpcenter/HelpCenterMenuContent.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 : Utilize ref and reactive for reactive state in Vue 3

Applied to files:

  • src/components/helpcenter/HelpCenterMenuContent.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/components/helpcenter/HelpCenterMenuContent.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/components/helpcenter/HelpCenterMenuContent.vue
  • src/platform/updates/components/WhatsNewPopup.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 Calendar component with DatePicker

Applied to files:

  • src/components/helpcenter/HelpCenterMenuContent.vue
📚 Learning: 2025-11-24T19:47:14.779Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:14.779Z
Learning: Applies to **/*.{ts,tsx,vue} : Use `const settingStore = useSettingStore()` and `settingStore.get('Comfy.SomeSetting')` to retrieve settings in TypeScript/Vue files

Applied to files:

  • src/components/helpcenter/HelpCenterMenuContent.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 OverlayPanel component with Popover

Applied to files:

  • src/platform/updates/components/WhatsNewPopup.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 : 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:

  • src/platform/updates/components/WhatsNewPopup.vue
📚 Learning: 2025-11-24T19:47:14.779Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:14.779Z
Learning: Applies to **/*.{vue,html} : Never use `dark:` or `dark-theme:` Tailwind variants - instead use semantic values from `style.css` theme, e.g. `bg-node-component-surface`

Applied to files:

  • src/platform/updates/components/WhatsNewPopup.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 defineExpose only for imperative operations (such as form.validate(), modal.open())

Applied to files:

  • src/platform/updates/components/WhatsNewPopup.vue
🪛 ESLint
src/components/helpcenter/HelpCenterMenuContent.vue

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

(import-x/no-unresolved)

src/platform/updates/components/WhatsNewPopup.vue

[error] 55-55: Unable to resolve path to module 'primevue/button'.

(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). (4)
  • GitHub Check: lint-and-format
  • GitHub Check: setup
  • GitHub Check: test
  • GitHub Check: collect
🔇 Additional comments (8)
src/components/helpcenter/HelpCenterMenuContent.vue (5)

289-308: Implementation looks good.

The new feedback and help menu items are properly implemented with i18n support and appropriate icons. Both items execute the same Comfy.ContactSupport command, which appears to be an intentional UX design choice to provide multiple entry points with different labeling.


184-184: Clean interface extension.

The addition of the optional showExternalIcon property to the MenuItem interface is well-implemented and consistently used throughout the component.


537-744: Excellent semantic token migration.

The styles have been successfully migrated from hardcoded colors to semantic design tokens (--interface-menu-surface, --interface-menu-stroke, --text-primary, etc.), which enables automatic light/dark theme support as intended in the PR objectives.

Note: Line 607 retains the hardcoded #ff3b30 for the red notification dot, which is appropriate as it's a semantic alert color that should remain consistent across themes.

As per coding guidelines, the component correctly uses tokens from style.css.


1-154: Well-structured template with proper accessibility.

The template section demonstrates excellent practices:

  • Semantic HTML elements (nav, article, section, button)
  • Proper ARIA attributes for accessibility
  • Consistent i18n usage via $t()
  • Responsive hover and keyboard interactions

156-534: Clean Composition API implementation.

The script section follows Vue 3 Composition API best practices:

  • Proper use of composables and lifecycle hooks
  • Well-typed TypeScript interfaces
  • Clean separation of concerns with computed properties
  • Proper event handling and state management

Note: The ESLint error about unresolved vue import (line 157) is a false positive—the component clearly functions correctly and this is a common tool configuration issue.

src/platform/updates/components/WhatsNewPopup.vue (3)

55-55: ESLint import error is likely a false positive.

The ESLint error "Unable to resolve path to module 'primevue/button'" is likely a false positive since PrimeVue is a core project dependency. If needed, verify that PrimeVue is properly installed and ESLint configuration includes proper resolution settings for PrimeVue imports.


185-436: Excellent use of semantic design tokens throughout!

The styling consistently uses semantic design tokens from the theme system (e.g., var(--interface-menu-surface), var(--text-primary), var(--button-hover-surface)) with no hardcoded colors or dark: variants. This perfectly aligns with the PR objective to enable automatic light/dark theme support.

As per coding guidelines: "Never use dark: or dark-theme: Tailwind variants - instead use semantic values from style.css theme."


18-18: HTML sanitization is already properly implemented with DOMPurify.

The renderMarkdownToHtml function in src/utils/markdownRendererUtil.ts (lines 41-59) already sanitizes HTML using DOMPurify before returning. At line 56, DOMPurify.sanitize(html, {...}) is called with appropriate allowed tags and attributes. The v-html directive in WhatsNewPopup.vue receives properly sanitized content, so no action is needed.

Likely an incorrect or invalid review comment.

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: 4

🧹 Nitpick comments (4)
src/platform/updates/components/ReleaseNotificationToast.test.ts (2)

148-149: Avoid as any type assertions.

The coding guidelines prohibit using as any. Since the component exposes methods via defineExpose, consider typing the wrapper's VM properly.

+// Define exposed methods type
+interface ReleaseNotificationToastExposed {
+  handleSkip: () => void
+  handleLearnMore: () => void
+  handleUpdate: () => void
+}
+
 // In tests, use:
-await (wrapper.vm as any).handleUpdate()
+await (wrapper.vm as unknown as ReleaseNotificationToastExposed).handleUpdate()

Alternatively, create a typed helper:

const getExposed = (w: VueWrapper) => 
  w.vm as unknown as ReleaseNotificationToastExposed

186-203: Fragile mock re-import pattern.

Using vi.importMock after the module is already mocked at the top of the file can lead to inconsistent behavior. The mock is already set up at lines 30-32.

Consider using the existing mock directly:

-  it('removes title from markdown content for toast display', async () => {
-    const mockMarkdownRendererModule = await vi.importMock(
-      '@/utils/markdownRendererUtil'
-    )
-    const mockMarkdownRenderer = vi.mocked(mockMarkdownRendererModule)
-      .renderMarkdownToHtml as any
-    mockMarkdownRenderer.mockReturnValue('<div>Content without title</div>')
+  it('removes title from markdown content for toast display', async () => {
+    const { renderMarkdownToHtml } = await import('@/utils/markdownRendererUtil')
+    const mockRenderer = vi.mocked(renderMarkdownToHtml)

Or clear and re-mock inline if custom return value is needed:

vi.mocked(renderMarkdownToHtml).mockReturnValue('<div>Content without title</div>')
src/platform/updates/components/WhatsNewPopup.vue (2)

36-47: Consider using the Button component for consistency.

The close button (lines 5-13) uses the design system Button component, but the footer action buttons use plain HTML <button> elements. For design system consistency and maintainability, consider using the Button component throughout.

Example refactor for the "Later" button:

-<button
-  class="action-secondary h-8 px-0 bg-transparent border-none text-sm font-normal rounded cursor-pointer"
+<Button
+  class="action-secondary"
+  :label="$t('whatsNewPopup.later')"
+  severity="secondary"
+  text
   @click="closePopup"
-\>
-  {{ $t('whatsNewPopup.later') }}
-</button>
+/>

Then adjust the CSS for .action-secondary to work with the Button component rather than raw HTML button styling.


165-171: Consider reducing the exposed API surface.

While show and hide are appropriate imperative operations for modal control, exposing handleCTA and closePopup may be unnecessary. The closePopup method is essentially a wrapper around hide with additional logic, and handleCTA is internal business logic.

If tests require these methods, consider whether the tests should interact with the component through its public interface (e.g., clicking buttons) rather than calling internal methods directly.

Based on learnings: "Use defineExpose only for imperative operations (such as form.validate(), modal.open())".

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between f3364e7 and 6a6dd61.

📒 Files selected for processing (3)
  • src/platform/updates/components/ReleaseNotificationToast.test.ts (1 hunks)
  • src/platform/updates/components/ReleaseNotificationToast.vue (6 hunks)
  • src/platform/updates/components/WhatsNewPopup.vue (7 hunks)
🧰 Additional context used
📓 Path-based instructions (17)
**/*.{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/platform/updates/components/ReleaseNotificationToast.test.ts
  • src/platform/updates/components/ReleaseNotificationToast.vue
  • src/platform/updates/components/WhatsNewPopup.vue
**/*.{ts,tsx,js}

📄 CodeRabbit inference engine (.cursorrules)

Use es-toolkit for utility functions

Files:

  • src/platform/updates/components/ReleaseNotificationToast.test.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/platform/updates/components/ReleaseNotificationToast.test.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/platform/updates/components/ReleaseNotificationToast.test.ts
  • src/platform/updates/components/ReleaseNotificationToast.vue
  • src/platform/updates/components/WhatsNewPopup.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/platform/updates/components/ReleaseNotificationToast.test.ts
  • src/platform/updates/components/ReleaseNotificationToast.vue
  • src/platform/updates/components/WhatsNewPopup.vue
src/**/*.ts

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

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

Files:

  • src/platform/updates/components/ReleaseNotificationToast.test.ts
**/*.{ts,tsx,js,jsx,vue}

📄 CodeRabbit inference engine (CLAUDE.md)

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

Files:

  • src/platform/updates/components/ReleaseNotificationToast.test.ts
  • src/platform/updates/components/ReleaseNotificationToast.vue
  • src/platform/updates/components/WhatsNewPopup.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:

  • src/platform/updates/components/ReleaseNotificationToast.test.ts
  • src/platform/updates/components/ReleaseNotificationToast.vue
  • src/platform/updates/components/WhatsNewPopup.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:

  • src/platform/updates/components/ReleaseNotificationToast.test.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/platform/updates/components/ReleaseNotificationToast.test.ts
  • src/platform/updates/components/ReleaseNotificationToast.vue
  • src/platform/updates/components/WhatsNewPopup.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/platform/updates/components/ReleaseNotificationToast.test.ts
  • src/platform/updates/components/ReleaseNotificationToast.vue
  • src/platform/updates/components/WhatsNewPopup.vue
src/**/*.{vue,ts,tsx}

📄 CodeRabbit inference engine (src/CLAUDE.md)

Follow Vue 3 composition API style guide

Files:

  • src/platform/updates/components/ReleaseNotificationToast.test.ts
  • src/platform/updates/components/ReleaseNotificationToast.vue
  • src/platform/updates/components/WhatsNewPopup.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/platform/updates/components/ReleaseNotificationToast.test.ts
  • src/platform/updates/components/ReleaseNotificationToast.vue
  • src/platform/updates/components/WhatsNewPopup.vue
**/*.{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:

  • src/platform/updates/components/ReleaseNotificationToast.test.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/platform/updates/components/ReleaseNotificationToast.vue
  • src/platform/updates/components/WhatsNewPopup.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/platform/updates/components/ReleaseNotificationToast.vue
  • src/platform/updates/components/WhatsNewPopup.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/platform/updates/components/ReleaseNotificationToast.vue
  • src/platform/updates/components/WhatsNewPopup.vue
🧠 Learnings (17)
📓 Common learnings
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-11-24T19:48:23.088Z
Learning: Pull requests must include a clear description, linked issues in the format `- Fixes #123`, and screenshots/GIFs for UI changes
📚 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:

  • src/platform/updates/components/ReleaseNotificationToast.test.ts
📚 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} : Always prefer vitest mock functions over writing verbose manual mocks

Applied to files:

  • src/platform/updates/components/ReleaseNotificationToast.test.ts
📚 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} : Mock external dependencies in tests

Applied to files:

  • src/platform/updates/components/ReleaseNotificationToast.test.ts
📚 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:

  • src/platform/updates/components/ReleaseNotificationToast.test.ts
📚 Learning: 2025-11-24T19:48:09.318Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: .cursor/rules/unit-test.mdc:0-0
Timestamp: 2025-11-24T19:48:09.318Z
Learning: Applies to test/**/*.{test,spec}.{js,ts,jsx,tsx} : Use `vitest` for unit testing in this project

Applied to files:

  • src/platform/updates/components/ReleaseNotificationToast.test.ts
📚 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} : Use existing test utilities rather than writing custom utilities

Applied to files:

  • src/platform/updates/components/ReleaseNotificationToast.test.ts
📚 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: Check tests-ui/README.md for test guidelines

Applied to files:

  • src/platform/updates/components/ReleaseNotificationToast.test.ts
📚 Learning: 2025-11-24T19:48:09.318Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: .cursor/rules/unit-test.mdc:0-0
Timestamp: 2025-11-24T19:48:09.318Z
Learning: Applies to test/**/*.{test,spec}.{js,ts,jsx,tsx} : Mocks should be cleanly written and easy to understand, with reusable mocks where possible

Applied to files:

  • src/platform/updates/components/ReleaseNotificationToast.test.ts
📚 Learning: 2025-11-24T19:48:23.088Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-11-24T19:48:23.088Z
Learning: Use Vitest (with happy-dom) for unit and component tests, and Playwright for E2E tests

Applied to files:

  • src/platform/updates/components/ReleaseNotificationToast.test.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} : Test across multiple viewports

Applied to files:

  • src/platform/updates/components/ReleaseNotificationToast.test.ts
📚 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 OverlayPanel component with Popover

Applied to files:

  • src/platform/updates/components/WhatsNewPopup.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 : 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:

  • src/platform/updates/components/WhatsNewPopup.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 InlineMessage component with Message

Applied to files:

  • src/platform/updates/components/WhatsNewPopup.vue
📚 Learning: 2025-11-24T19:47:14.779Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:14.779Z
Learning: Applies to **/*.{vue,html} : Never use `dark:` or `dark-theme:` Tailwind variants - instead use semantic values from `style.css` theme, e.g. `bg-node-component-surface`

Applied to files:

  • src/platform/updates/components/WhatsNewPopup.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/platform/updates/components/WhatsNewPopup.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 defineExpose only for imperative operations (such as form.validate(), modal.open())

Applied to files:

  • src/platform/updates/components/WhatsNewPopup.vue
🧬 Code graph analysis (1)
src/platform/updates/components/ReleaseNotificationToast.test.ts (1)
src/platform/updates/common/releaseService.ts (1)
  • ReleaseNote (10-10)
🪛 ESLint
src/platform/updates/components/ReleaseNotificationToast.test.ts

[error] 1-1: Resolve error: EACCES: permission denied, open '/sgJrlmRHQy'
at Object.writeFileSync (node:fs:2409:20)
at l (file:///home/jailuser/git/node_modules/.pnpm/[email protected]/node_modules/get-tsconfig/dist/index.mjs:7:13670)
at createFilesMatcher (file:///home/jailuser/git/node_modules/.pnpm/[email protected]/node_modules/get-tsconfig/dist/index.mjs:7:14422)
at resolve (file:///home/jailuser/git/node_modules/.pnpm/[email protected][email protected]_@typescript-eslin_da4796079dab5a32abf73f9910d12370/node_modules/eslint-import-resolver-typescript/lib/index.js:70:65)
at Object.resolve (file:///home/jailuser/git/node_modules/.pnpm/[email protected][email protected]_@typescript-eslin_da4796079dab5a32abf73f9910d12370/node_modules/eslint-import-resolver-typescript/lib/index.js:147:20)
at file:///home/jailuser/git/node_modules/.pnpm/eslint-plugin-import-x@4.16.1_@typescript-eslint[email protected]_eslint@[email protected]__d4b6b79e6f12f59d34d55ebbf27dc73f/node_modules/eslint-plugin-import-x/lib/utils/resolve.js:170:69
at setRuleContext (/home/jailuser/git/node_modules/.pnpm/[email protected][email protected]/node_modules/eslint-import-context/lib/index.js:23:20)
at fullResolve (file:///home/jailuser/git/node_modules/.pnpm/eslint-plugin-import-x@4.16.1_@typescript-eslint[email protected]_eslint@[email protected]__d4b6b79e6f12f59d34d55ebbf27dc73f/node_modules/eslint-plugin-import-x/lib/utils/resolve.js:170:30)
at relative (file:///home/jailuser/git/node_modules/.pnpm/eslint-plugin-import-x@4.16.1_@typescript-eslint[email protected]_eslint@[email protected]__d4b6b79e6f12f59d34d55ebbf27dc73f/node_modules/eslint-plugin-import-x/lib/utils/resolve.js:215:12)
at resolve (file:///home/jailuser/git/node_modules/.pnpm/eslint-plugin-import-x@4.16.1_@typescript-eslint[email protected]_eslint@[email protected]__d4b6b79e6f12f59d34d55ebbf27dc73f/node_modules/eslint-plugin-import-x/lib/utils/resolve.js:220:16)
at ExportMap.get (file:///home/jailuser/git/node_modules/.pnpm/eslint-plugin-import-x@4.16.1_@typescript-eslint[email protected]_eslint@[email protected]__d4b6b79e6f12f59d34d55ebbf27dc73f/node_modules/eslint-plugin-import-x/lib/utils/export-map.js:88:22)
at processBodyStatement (file:///home/jailuser/git/node_modules/.pnpm/eslint-plugin-import-x@4.16.1_@typescript-eslint[email protected]_eslint@[email protected]__d4b6b79e6f12f59d34d55ebbf27dc73f/node_modules/eslint-plugin-import-x/lib/rules/namespace.js:9:31)
at Program (file:///home/jailuser/git/node_modules/.pnpm/eslint-plugin-import-x@4.16.1_@typescript-eslint[email protected]_eslint@[email protected]__d4b6b79e6f12f59d34d55ebbf27dc73f/node_modules/eslint-plugin-import-x/lib/rules/namespace.js:100:21)
at ruleErrorHandler (/home/jailuser/git/node_modules/.pnpm/[email protected][email protected]/node_modules/eslint/lib/linter/linter.js:1173:33)
at /home/jailuser/git/node_modules/.pnpm/[email protected][email protected]/node_modules/eslint/lib/linter/source-code-visitor.js:76:46
at Array.forEach ()
at SourceCodeVisitor.callSync (/home/jailuser/git/node_modules/.pnpm/[email protected][email protected]/node_modules/eslint/lib/linter/source-code-visitor.js:76:30)
at /home/jailuser/git/node_modules/.pnpm/[email protected][email protected]/node_modules/eslint/lib/linter/source-code-traverser.js:291:18
at Array.forEach ()
at SourceCodeTraverser.traverseSync (/home/jailuser/git/node_modules/.pnpm/[email protected][email protected]/node_modules/eslint/lib/linter/source-code-traverser.js:290:10)
at runRules (/home/jailuser/git/node_modules/.pnpm/[email protected][email protected]/node_modules/eslint/lib/linter/linter.js:1214:12)
at #flatVerifyWithoutProcessors (/home/jailuser/git/node_modules/.pnpm/[email protected][email protected]/node_modules/eslint/lib/linter/linter.js:2101:4)
at Linter._verifyWithFlatConfigArrayAndWithoutProcessors (/home/jailuser/git/node_modules/.pnpm/[email protected][email protected]/node_modules/eslint/lib/linter/linter.js:2189:43)
at Linter._verifyWithFlatConfigArray (/home/jailuser/git/node_modules/.pnpm/[email protected][email protected]/node_modules/eslint/lib/linter/linter.js:2292:15)
at Linter.verify (/home/jailuser/git/node_modules/.pnpm/[email protected][email protected]/node_modules/eslint/lib/linter/linter.js:1677:10)
at Linter.verifyAndFix (/home/jailuser/git/node_modules/.pnpm/[email protected][email protected]/node_modules/eslint/lib/linter/linter.js:2557:20)
at verifyText (/home/jailuser/git/node_modules/.pnpm/[email protected][email protected]/node_modules/eslint/lib/eslint/eslint-helpers.js:1179:45)
at readAndVerifyFile (/home/jailuser/git/node_modules/.pnpm/[email protected][email protected]/node_modules/eslint/lib/eslint/eslint-helpers.js:1320:10)

(import-x/namespace)


[error] 1-1: Resolve error: EACCES: permission denied, open '/FdBphMzGyV'
at Object.writeFileSync (node:fs:2409:20)
at l (file:///home/jailuser/git/node_modules/.pnpm/[email protected]/node_modules/get-tsconfig/dist/index.mjs:7:13670)
at createFilesMatcher (file:///home/jailuser/git/node_modules/.pnpm/[email protected]/node_modules/get-tsconfig/dist/index.mjs:7:14422)
at resolve (file:///home/jailuser/git/node_modules/.pnpm/[email protected][email protected]_@typescript-eslin_da4796079dab5a32abf73f9910d12370/node_modules/eslint-import-resolver-typescript/lib/index.js:70:65)
at Object.resolve (file:///home/jailuser/git/node_modules/.pnpm/[email protected][email protected]_@typescript-eslin_da4796079dab5a32abf73f9910d12370/node_modules/eslint-import-resolver-typescript/lib/index.js:147:20)
at file:///home/jailuser/git/node_modules/.pnpm/eslint-plugin-import-x@4.16.1_@typescript-eslint[email protected]_eslint@[email protected]__d4b6b79e6f12f59d34d55ebbf27dc73f/node_modules/eslint-plugin-import-x/lib/utils/resolve.js:170:69
at setRuleContext (/home/jailuser/git/node_modules/.pnpm/[email protected][email protected]/node_modules/eslint-import-context/lib/index.js:23:20)
at fullResolve (file:///home/jailuser/git/node_modules/.pnpm/eslint-plugin-import-x@4.16.1_@typescript-eslint[email protected]_eslint@[email protected]__d4b6b79e6f12f59d34d55ebbf27dc73f/node_modules/eslint-plugin-import-x/lib/utils/resolve.js:170:30)
at relative (file:///home/jailuser/git/node_modules/.pnpm/eslint-plugin-import-x@4.16.1_@typescript-eslint[email protected]_eslint@[email protected]__d4b6b79e6f12f59d34d55ebbf27dc73f/node_modules/eslint-plugin-import-x/lib/utils/resolve.js:215:12)
at resolve (file:///home/jailuser/git/node_modules/.pnpm/eslint-plugin-import-x@4.16.1_@typescript-eslint[email protected]_eslint@[email protected]__d4b6b79e6f12f59d34d55ebbf27dc73f/node_modules/eslint-plugin-import-x/lib/utils/resolve.js:220:16)
at importType (file:///home/jailuser/git/node_modules/.pnpm/eslint-plugin-import-x@4.16.1_@typescript-eslint[email protected]_eslint@[email protected]__d4b6b79e6f12f59d34d55ebbf27dc73f/node_modules/eslint-plugin-import-x/lib/utils/import-type.js:126:63)
at checkImportForRelativePackage (file:///home/jailuser/git/node_modules/.pnpm/eslint-plugin-import-x@4.16.1_@typescript-eslint[email protected]_eslint@[email protected]__d4b6b79e6f12f59d34d55ebbf27dc73f/node_modules/eslint-plugin-import-x/lib/rules/no-relative-packages.js:15:38)
at file:///home/jailuser/git/node_modules/.pnpm/eslint-plugin-import-x@4.16.1_@typescript-eslint[email protected]_eslint@[email protected]__d4b6b79e6f12f59d34d55ebbf27dc73f/node_modules/eslint-plugin-import-x/lib/rules/no-relative-packages.js:59:40
at checkSourceValue (file:///home/jailuser/git/node_modules/.pnpm/eslint-plugin-import-x@4.16.1_@typescript-eslint[email protected]_eslint@[email protected]__d4b6b79e6f12f59d34d55ebbf27dc73f/node_modules/eslint-plugin-import-x/lib/utils/module-visitor.js:14:9)
at checkSource (file:///home/jailuser/git/node_modules/.pnpm/eslint-plugin-import-x@4.16.1_@typescript-eslint[email protected]_eslint@[email protected]__d4b6b79e6f12f59d34d55ebbf27dc73f/node_modules/eslint-plugin-import-x/lib/utils/module-visitor.js:17:9)
at ruleErrorHandler (/home/jailuser/git/node_modules/.pnpm/[email protected][email protected]/node_modules/eslint/lib/linter/linter.js:1173:33)
at /home/jailuser/git/node_modules/.pnpm/[email protected][email protected]/node_modules/eslint/lib/linter/source-code-visitor.js:76:46
at Array.forEach ()
at SourceCodeVisitor.callSync (/home/jailuser/git/node_modules/.pnpm/[email protected][email protected]/node_modules/eslint/lib/linter/source-code-visitor.js:76:30)
at /home/jailuser/git/node_modules/.pnpm/[email protected][email protected]/node_modules/eslint/lib/linter/source-code-traverser.js:291:18
at Array.forEach ()
at SourceCodeTraverser.traverseSync (/home/jailuser/git/node_modules/.pnpm/[email protected][email protected]/node_modules/eslint/lib/linter/source-code-traverser.js:290:10)
at runRules (/home/jailuser/git/node_modules/.pnpm/[email protected][email protected]/node_modules/eslint/lib/linter/linter.js:1214:12)
at #flatVerifyWithoutProcessors (/home/jailuser/git/node_modules/.pnpm/[email protected][email protected]/node_modules/eslint/lib/linter/linter.js:2101:4)
at Linter._verifyWithFlatConfigArrayAndWithoutProcessors (/home/jailuser/git/node_modules/.pnpm/[email protected][email protected]/node_modules/eslint/lib/linter/linter.js:2189:43)
at Linter._verifyWithFlatConfigArray (/home/jailuser/git/node_modules/.pnpm/[email protected][email protected]/node_modules/eslint/lib/linter/linter.js:2292:15)
at Linter.verify (/home/jailuser/git/node_modules/.pnpm/[email protected][email protected]/node_modules/eslint/lib/linter/linter.js:1677:10)
at Linter.verifyAndFix (/home/jailuser/git/node_modules/.pnpm/[email protected][email protected]/node_modules/eslint/lib/linter/linter.js:2557:20)
at verifyText (/home/jailuser/git/node_modules/.pnpm/[email protected][email protected]/node_modules/eslint/lib/eslint/eslint-helpers.js:1179:45)
at readAndVerifyFile (/home/jailuser/git/node_modules/.pnpm/[email protected][email protected]/node_modules/eslint/lib/eslint/eslint-helpers.js:1320:10)

(import-x/no-relative-packages)


[error] 1-1: Resolve error: EACCES: permission denied, open '/yDzIyaTNLn'
at Object.writeFileSync (node:fs:2409:20)
at l (file:///home/jailuser/git/node_modules/.pnpm/[email protected]/node_modules/get-tsconfig/dist/index.mjs:7:13670)
at createFilesMatcher (file:///home/jailuser/git/node_modules/.pnpm/[email protected]/node_modules/get-tsconfig/dist/index.mjs:7:14422)
at resolve (file:///home/jailuser/git/node_modules/.pnpm/[email protected][email protected]_@typescript-eslin_da4796079dab5a32abf73f9910d12370/node_modules/eslint-import-resolver-typescript/lib/index.js:70:65)
at Object.resolve (file:///home/jailuser/git/node_modules/.pnpm/[email protected][email protected]_@typescript-eslin_da4796079dab5a32abf73f9910d12370/node_modules/eslint-import-resolver-typescript/lib/index.js:147:20)
at file:///home/jailuser/git/node_modules/.pnpm/eslint-plugin-import-x@4.16.1_@typescript-eslint[email protected]_eslint@[email protected]__d4b6b79e6f12f59d34d55ebbf27dc73f/node_modules/eslint-plugin-import-x/lib/utils/resolve.js:170:69
at setRuleContext (/home/jailuser/git/node_modules/.pnpm/[email protected][email protected]/node_modules/eslint-import-context/lib/index.js:23:20)
at fullResolve (file:///home/jailuser/git/node_modules/.pnpm/eslint-plugin-import-x@4.16.1_@typescript-eslint[email protected]_eslint@[email protected]__d4b6b79e6f12f59d34d55ebbf27dc73f/node_modules/eslint-plugin-import-x/lib/utils/resolve.js:170:30)
at relative (file:///home/jailuser/git/node_modules/.pnpm/eslint-plugin-import-x@4.16.1_@typescript-eslint[email protected]_eslint@[email protected]__d4b6b79e6f12f59d34d55ebbf27dc73f/node_modules/eslint-plugin-import-x/lib/utils/resolve.js:215:12)
at resolve (file:///home/jailuser/git/node_modules/.pnpm/eslint-plugin-import-x@4.16.1_@typescript-eslint[email protected]_eslint@[email protected]__d4b6b79e6f12f59d34d55ebbf27dc73f/node_modules/eslint-plugin-import-x/lib/utils/resolve.js:220:16)
at checkSourceValue (file:///home/jailuser/git/node_modules/.pnpm/eslint-plugin-import-x@4.16.1_@typescript-eslint[email protected]_eslint@[email protected]__d4b6b79e6f12f59d34d55ebbf27dc73f/node_modules/eslint-plugin-import-x/lib/rules/no-unresolved.js:31:34)
at checkSourceValue (file:///home/jailuser/git/node_modules/.pnpm/eslint-plugin-import-x@4.16.1_@typescript-eslint[email protected]_eslint@[email protected]__d4b6b79e6f12f59d34d55ebbf27dc73f/node_modules/eslint-plugin-import-x/lib/utils/module-visitor.js:14:9)
at checkSource (file:///home/jailuser/git/node_modules/.pnpm/eslint-plugin-import-x@4.16.1_@typescript-eslint[email protected]_eslint@[email protected]__d4b6b79e6f12f59d34d55ebbf27dc73f/node_modules/eslint-plugin-import-x/lib/utils/module-visitor.js:17:9)
at ruleErrorHandler (/home/jailuser/git/node_modules/.pnpm/[email protected][email protected]/node_modules/eslint/lib/linter/linter.js:1173:33)
at /home/jailuser/git/node_modules/.pnpm/[email protected][email protected]/node_modules/eslint/lib/linter/source-code-visitor.js:76:46
at Array.forEach ()
at SourceCodeVisitor.callSync (/home/jailuser/git/node_modules/.pnpm/[email protected][email protected]/node_modules/eslint/lib/linter/source-code-visitor.js:76:30)
at /home/jailuser/git/node_modules/.pnpm/[email protected][email protected]/node_modules/eslint/lib/linter/source-code-traverser.js:291:18
at Array.forEach ()
at SourceCodeTraverser.traverseSync (/home/jailuser/git/node_modules/.pnpm/[email protected][email protected]/node_modules/eslint/lib/linter/source-code-traverser.js:290:10)
at runRules (/home/jailuser/git/node_modules/.pnpm/[email protected][email protected]/node_modules/eslint/lib/linter/linter.js:1214:12)
at #flatVerifyWithoutProcessors (/home/jailuser/git/node_modules/.pnpm/[email protected][email protected]/node_modules/eslint/lib/linter/linter.js:2101:4)
at Linter._verifyWithFlatConfigArrayAndWithoutProcessors (/home/jailuser/git/node_modules/.pnpm/[email protected][email protected]/node_modules/eslint/lib/linter/linter.js:2189:43)
at Linter._verifyWithFlatConfigArray (/home/jailuser/git/node_modules/.pnpm/[email protected][email protected]/node_modules/eslint/lib/linter/linter.js:2292:15)
at Linter.verify (/home/jailuser/git/node_modules/.pnpm/[email protected][email protected]/node_modules/eslint/lib/linter/linter.js:1677:10)
at Linter.verifyAndFix (/home/jailuser/git/node_modules/.pnpm/[email protected][email protected]/node_modules/eslint/lib/linter/linter.js:2557:20)
at verifyText (/home/jailuser/git/node_modules/.pnpm/[email protected][email protected]/node_modules/eslint/lib/eslint/eslint-helpers.js:1179:45)
at readAndVerifyFile (/home/jailuser/git/node_modules/.pnpm/[email protected][email protected]/node_modules/eslint/lib/eslint/eslint-helpers.js:1320:10)

(import-x/no-unresolved)


[error] 1-1: Resolve error: EACCES: permission denied, open '/ZGZlDfswZk'
at Object.writeFileSync (node:fs:2409:20)
at l (file:///home/jailuser/git/node_modules/.pnpm/[email protected]/node_modules/get-tsconfig/dist/index.mjs:7:13670)
at createFilesMatcher (file:///home/jailuser/git/node_modules/.pnpm/[email protected]/node_modules/get-tsconfig/dist/index.mjs:7:14422)
at resolve (file:///home/jailuser/git/node_modules/.pnpm/[email protected][email protected]_@typescript-eslin_da4796079dab5a32abf73f9910d12370/node_modules/eslint-import-resolver-typescript/lib/index.js:70:65)
at Object.resolve (file:///home/jailuser/git/node_modules/.pnpm/[email protected][email protected]_@typescript-eslin_da4796079dab5a32abf73f9910d12370/node_modules/eslint-import-resolver-typescript/lib/index.js:147:20)
at file:///home/jailuser/git/node_modules/.pnpm/eslint-plugin-import-x@4.16.1_@typescript-eslint[email protected]_eslint@[email protected]__d4b6b79e6f12f59d34d55ebbf27dc73f/node_modules/eslint-plugin-import-x/lib/utils/resolve.js:170:69
at setRuleContext (/home/jailuser/git/node_modules/.pnpm/[email protected][email protected]/node_modules/eslint-import-context/lib/index.js:23:20)
at fullResolve (file:///home/jailuser/git/node_modules/.pnpm/eslint-plugin-import-x@4.16.1_@typescript-eslint[email protected]_eslint@[email protected]__d4b6b79e6f12f59d34d55ebbf27dc73f/node_modules/eslint-plugin-import-x/lib/utils/resolve.js:170:30)
at relative (file:///home/jailuser/git/node_modules/.pnpm/eslint-plugin-import-x@4.16.1_@typescript-eslint[email protected]_eslint@[email protected]__d4b6b79e6f12f59d34d55ebbf27dc73f/node_modules/eslint-plugin-import-x/lib/utils/resolve.js:215:12)
at resolve (file:///home/jailuser/git/node_modules/.pnpm/eslint-plugin-import-x@4.16.1_@typescript-eslint[email protected]_eslint@[email protected]__d4b6b79e6f12f59d34d55ebbf27dc73f/node_modules/eslint-plugin-import-x/lib/utils/resolve.js:220:16)
at file:///home/jailuser/git/node_modules/.pnpm/eslint-plugin-import-x@4.16.1_@typescript-eslint[email protected]_eslint@[email protected]__d4b6b79e6f12f59d34d55ebbf27dc73f/node_modules/eslint-plugin-import-x/lib/rules/no-useless-path-segments.js:58:34
at checkSourceValue (file:///home/jailuser/git/node_modules/.pnpm/eslint-plugin-import-x@4.16.1_@typescript-eslint[email protected]_eslint@[email protected]__d4b6b79e6f12f59d34d55ebbf27dc73f/node_modules/eslint-plugin-import-x/lib/utils/module-visitor.js:14:9)
at checkSource (file:///home/jailuser/git/node_modules/.pnpm/eslint-plugin-import-x@4.16.1_@typescript-eslint[email protected]_eslint@[email protected]__d4b6b79e6f12f59d34d55ebbf27dc73f/node_modules/eslint-plugin-import-x/lib/utils/module-visitor.js:17:9)
at ruleErrorHandler (/home/jailuser/git/node_modules/.pnpm/[email protected][email protected]/node_modules/eslint/lib/linter/linter.js:1173:33)
at /home/jailuser/git/node_modules/.pnpm/[email protected][email protected]/node_modules/eslint/lib/linter/source-code-visitor.js:76:46
at Array.forEach ()
at SourceCodeVisitor.callSync (/home/jailuser/git/node_modules/.pnpm/[email protected][email protected]/node_modules/eslint/lib/linter/source-code-visitor.js:76:30)
at /home/jailuser/git/node_modules/.pnpm/[email protected][email protected]/node_modules/eslint/lib/linter/source-code-traverser.js:291:18
at Array.forEach ()
at SourceCodeTraverser.traverseSync (/home/jailuser/git/node_modules/.pnpm/[email protected][email protected]/node_modules/eslint/lib/linter/source-code-traverser.js:290:10)
at runRules (/home/jailuser/git/node_modules/.pnpm/[email protected][email protected]/node_modules/eslint/lib/linter/linter.js:1214:12)
at #flatVerifyWithoutProcessors (/home/jailuser/git/node_modules/.pnpm/[email protected][email protected]/node_modules/eslint/lib/linter/linter.js:2101:4)
at Linter._verifyWithFlatConfigArrayAndWithoutProcessors (/home/jailuser/git/node_modules/.pnpm/[email protected][email protected]/node_modules/eslint/lib/linter/linter.js:2189:43)
at Linter._verifyWithFlatConfigArray (/home/jailuser/git/node_modules/.pnpm/[email protected][email protected]/node_modules/eslint/lib/linter/linter.js:2292:15)
at Linter.verify (/home/jailuser/git/node_modules/.pnpm/[email protected][email protected]/node_modules/eslint/lib/linter/linter.js:1677:10)
at Linter.verifyAndFix (/home/jailuser/git/node_modules/.pnpm/[email protected][email protected]/node_modules/eslint/lib/linter/linter.js:2557:20)
at verifyText (/home/jailuser/git/node_modules/.pnpm/[email protected][email protected]/node_modules/eslint/lib/eslint/eslint-helpers.js:1179:45)
at readAndVerifyFile (/home/jailuser/git/node_modules/.pnpm/[email protected][email protected]/node_modules/eslint/lib/eslint/eslint-helpers.js:1320:10)

(import-x/no-useless-path-segments)


[error] 1-1: Resolve error: EACCES: permission denied, open '/VnVBoGlnHP'
at Object.writeFileSync (node:fs:2409:20)
at l (file:///home/jailuser/git/node_modules/.pnpm/[email protected]/node_modules/get-tsconfig/dist/index.mjs:7:13670)
at createFilesMatcher (file:///home/jailuser/git/node_modules/.pnpm/[email protected]/node_modules/get-tsconfig/dist/index.mjs:7:14422)
at resolve (file:///home/jailuser/git/node_modules/.pnpm/[email protected][email protected]_@typescript-eslin_da4796079dab5a32abf73f9910d12370/node_modules/eslint-import-resolver-typescript/lib/index.js:70:65)
at Object.resolve (file:///home/jailuser/git/node_modules/.pnpm/[email protected][email protected]_@typescript-eslin_da4796079dab5a32abf73f9910d12370/node_modules/eslint-import-resolver-typescript/lib/index.js:147:20)
at file:///home/jailuser/git/node_modules/.pnpm/eslint-plugin-import-x@4.16.1_@typescript-eslint[email protected]_eslint@[email protected]__d4b6b79e6f12f59d34d55ebbf27dc73f/node_modules/eslint-plugin-import-x/lib/utils/resolve.js:170:69
at setRuleContext (/home/jailuser/git/node_modules/.pnpm/[email protected][email protected]/node_modules/eslint-import-context/lib/index.js:23:20)
at fullResolve (file:///home/jailuser/git/node_modules/.pnpm/eslint-plugin-import-x@4.16.1_@typescript-eslint[email protected]_eslint@[email protected]__d4b6b79e6f12f59d34d55ebbf27dc73f/node_modules/eslint-plugin-import-x/lib/utils/resolve.js:170:30)
at relative (file:///home/jailuser/git/node_modules/.pnpm/eslint-plugin-import-x@4.16.1_@typescript-eslint[email protected]_eslint@[email protected]__d4b6b79e6f12f59d34d55ebbf27dc73f/node_modules/eslint-plugin-import-x/lib/utils/resolve.js:215:12)
at resolve (file:///home/jailuser/git/node_modules/.pnpm/eslint-plugin-import-x@4.16.1_@typescript-eslint[email protected]_eslint@[email protected]__d4b6b79e6f12f59d34d55ebbf27dc73f/node_modules/eslint-plugin-import-x/lib/utils/resolve.js:220:16)
at ExportMap.get (file:///home/jailuser/git/node_modules/.pnpm/eslint-plugin-import-x@4.16.1_@typescript-eslint[email protected]_eslint@[email protected]__d4b6b79e6f12f59d34d55ebbf27dc73f/node_modules/eslint-plugin-import-x/lib/utils/export-map.js:88:22)
at checkDefault (file:///home/jailuser/git/node_modules/.pnpm/eslint-plugin-import-x@4.16.1_@typescript-eslint[email protected]_eslint@[email protected]__d4b6b79e6f12f59d34d55ebbf27dc73f/node_modules/eslint-plugin-import-x/lib/rules/default.js:22:39)
at ruleErrorHandler (/home/jailuser/git/node_modules/.pnpm/[email protected][email protected]/node_modules/eslint/lib/linter/linter.js:1173:33)
at /home/jailuser/git/node_modules/.pnpm/[email protected][email protected]/node_modules/eslint/lib/linter/source-code-visitor.js:76:46
at Array.forEach ()
at SourceCodeVisitor.callSync (/home/jailuser/git/node_modules/.pnpm/[email protected][email protected]/node_modules/eslint/lib/linter/source-code-visitor.js:76:30)
at /home/jailuser/git/node_modules/.pnpm/[email protected][email protected]/node_modules/eslint/lib/linter/source-code-traverser.js:291:18
at Array.forEach ()
at SourceCodeTraverser.traverseSync (/home/jailuser/git/node_modules/.pnpm/[email protected][email protected]/node_modules/eslint/lib/linter/source-code-traverser.js:290:10)
at runRules (/home/jailuser/git/node_modules/.pnpm/[email protected][email protected]/node_modules/eslint/lib/linter/linter.js:1214:12)
at #flatVerifyWithoutProcessors (/home/jailuser/git/node_modules/.pnpm/[email protected][email protected]/node_modules/eslint/lib/linter/linter.js:2101:4)
at Linter._verifyWithFlatConfigArrayAndWithoutProcessors (/home/jailuser/git/node_modules/.pnpm/[email protected][email protected]/node_modules/eslint/lib/linter/linter.js:2189:43)
at Linter._verifyWithFlatConfigArray (/home/jailuser/git/node_modules/.pnpm/[email protected][email protected]/node_modules/eslint/lib/linter/linter.js:2292:15)
at Linter.verify (/home/jailuser/git/node_modules/.pnpm/[email protected][email protected]/node_modules/eslint/lib/linter/linter.js:1677:10)
at Linter.verifyAndFix (/home/jailuser/git/node_modules/.pnpm/[email protected][email protected]/node_modules/eslint/lib/linter/linter.js:2557:20)
at verifyText (/home/jailuser/git/node_modules/.pnpm/[email protected][email protected]/node_modules/eslint/lib/eslint/eslint-helpers.js:1179:45)
at readAndVerifyFile (/home/jailuser/git/node_modules/.pnpm/[email protected][email protected]/node_modules/eslint/lib/eslint/eslint-helpers.js:1320:10)

(import-x/default)


[error] 2-2: Unable to resolve path to module '@vue/test-utils'.

(import-x/no-unresolved)


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

(import-x/no-unresolved)


[error] 6-6: Unable to resolve path to module './ReleaseNotificationToast.vue'.

(import-x/no-unresolved)

src/platform/updates/components/ReleaseNotificationToast.vue

[error] 72-72: Unable to resolve path to module '@/utils/markdownRendererUtil'.

(import-x/no-unresolved)

src/platform/updates/components/WhatsNewPopup.vue

[error] 55-55: Unable to resolve path to module 'primevue/button'.

(import-x/no-unresolved)

🔇 Additional comments (4)
src/platform/updates/components/ReleaseNotificationToast.test.ts (2)

84-112: Good test coverage for basic rendering.

Tests properly verify component visibility, icon presence, and version display.


228-276: Comprehensive timer behavior tests.

Good coverage for auto-hide and manual dismissal timer cleanup using fake timers.

src/platform/updates/components/ReleaseNotificationToast.vue (2)

3-63: Well-structured component layout with semantic Tailwind classes.

The card-like design with proper spacing, flex layout, and responsive overflow handling is clean. Good use of semantic color tokens (bg-base-background, text-muted-foreground, etc.) aligning with the design system migration goals.


195-201: Good practice exposing methods for testing.

Using defineExpose to expose handlers enables direct testing of component behavior.

- Add proper semantic design tokens (corner-radius, blue surface)
- Convert hardcoded colors to theme-aware tokens in toast and popup
- Implement Figma-compliant styling with image support
- Add comprehensive component tests for behavioral validation
- Update translation strings for improved UI copy
- Remove temporary mock data from WhatsNewPopup component
- Fix i18n mocking issues in both test suites
- Fix TypeScript errors with vi.mocked calls
- Update failing tests to use direct method calls instead of DOM events
- Remove duplicate/outdated test file
- All 22 tests now passing
…se notifications

- Replace hardcoded colors with semantic design tokens (bg-primary-background-hover, bg-secondary-background)
- Add proper height constraints and scrolling for long content in toast
- Remove image support from toast component (design requirement)
- Fix empty content handling - components don't show when no meaningful content
- Add comprehensive Storybook stories for both WhatsNewPopup and ReleaseNotificationToast
- Fix TypeScript errors by updating mock data with required ReleaseNote properties
- Clean up redundant CSS and remove development console.log statements
- Ensure proper markdown rendering with bullet points using dash syntax
…ling

- Update test selectors to match new Tailwind-based template structure
- Fix component behavior to show fallback content instead of disappearing
- Add proper mock setup for tests requiring shouldShow state
- Update button and link selectors for new component structure
- Fix TypeScript error with undefined button reference

Components now gracefully handle empty content by showing meaningful
fallback messages instead of returning null.
Add DOMPurify sanitization to HTML content rendered via v-html in both:
- ReleaseNotificationToast.vue: Sanitize all HTML output including fallback content
- WhatsNewPopup.vue: Sanitize fallback and error HTML content

Markdown content is already sanitized by renderMarkdownToHtml utility.
- Use t('releaseToast.description') instead of hardcoded English fallback text
- Fix rel attribute to use space-separated values (noopener noreferrer)
@christian-byrne christian-byrne force-pushed the style/whatsnew-light-mode branch from 02bbbef to 11775ff Compare December 3, 2025 22:04
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

♻️ Duplicate comments (1)
src/platform/updates/components/WhatsNewPopup.vue (1)

55-56: Fix incorrect Button import path.

This import was flagged in a previous review. The project uses a custom design system Button component, not PrimeVue's Button directly.

Apply this diff:

-import Button from 'primevue/button'
+import Button from '@/design-system/components/Button.vue'
🧹 Nitpick comments (7)
src/platform/updates/components/WhatsNewPopup.test.ts (2)

11-41: Consider consolidating duplicate translation mocks.

The same translation dictionary is defined three times (lines 11-25, 27-41, and 73-82). Consider extracting to a shared constant to reduce duplication and maintenance burden.

+const mockTranslations: Record<string, string> = {
+  'g.close': 'Close',
+  'whatsNewPopup.later': 'Later',
+  'whatsNewPopup.update': 'Update',
+  'whatsNewPopup.learnMore': 'Learn More',
+  'whatsNewPopup.noReleaseNotes': 'No release notes available'
+}
+
 vi.mock('@/i18n', () => ({
   t: (key: string, params?: Record<string, string>) => {
-    const translations: Record<string, string> = {
-      'g.close': 'Close',
-      'whatsNewPopup.later': 'Later',
-      'whatsNewPopup.update': 'Update',
-      'whatsNewPopup.learnMore': 'Learn More',
-      'whatsNewPopup.noReleaseNotes': 'No release notes available'
-    }
     return params
-      ? `${translations[key] || key}:${JSON.stringify(params)}`
-      : translations[key] || key
+      ? `${mockTranslations[key] || key}:${JSON.stringify(params)}`
+      : mockTranslations[key] || key
   },
   d: (date: Date) => date.toLocaleDateString()
 }))

196-200: Avoid as any type assertion.

Per coding guidelines, avoid as any type assertions. Consider using proper typing for the mocked module.

-  it('processes markdown content correctly', async () => {
-    const mockMarkdownRendererModule = await vi.importMock(
-      '@/utils/markdownRendererUtil'
-    )
-    const mockMarkdownRenderer = vi.mocked(mockMarkdownRendererModule)
-      .renderMarkdownToHtml as any
-    mockMarkdownRenderer.mockReturnValue('<h1>Processed Content</h1>')
+  it('processes markdown content correctly', async () => {
+    const mockMarkdownRendererModule = await vi.importMock<
+      typeof import('@/utils/markdownRendererUtil')
+    >('@/utils/markdownRendererUtil')
+    const mockMarkdownRenderer = vi.mocked(
+      mockMarkdownRendererModule.renderMarkdownToHtml
+    )
+    mockMarkdownRenderer.mockReturnValue('<h1>Processed Content</h1>')
src/platform/updates/components/ReleaseNotificationToast.stories.ts (2)

112-118: Use semantic color token instead of hardcoded gray.

Per coding guidelines, avoid hardcoded colors in templates. Replace bg-gray-900 with a semantic token from the design system.

       return {
         template: `
-          <div class="min-h-screen flex items-center justify-center bg-gray-900 p-8">
+          <div class="min-h-screen flex items-center justify-center bg-base-background p-8">
             <story />
           </div>
         `
       }

95-102: Object.defineProperty approach for computed property mocking is fragile.

While this works for Storybook, using Object.defineProperty to override Pinia getters can cause issues if the store is reactive. Consider using a more robust approach.

-      // Force the computed properties to return the values we want
-      Object.defineProperty(releaseStore, 'recentRelease', {
-        value: context.args.releaseData,
-        writable: true
-      })
-      Object.defineProperty(releaseStore, 'shouldShowToast', {
-        value: true,
-        writable: true
-      })
+      // Patch store state directly for Storybook
+      releaseStore.$patch({
+        releases: [context.args.releaseData]
+      })
+      // Mock getters via spyOn if needed, or rely on computed derivation

Note: This depends on how the store is structured. If recentRelease and shouldShowToast are getters derived from releases, patching releases should suffice.

src/components/helpcenter/HelpCenterMenuContent.vue (2)

34-43: Use Tailwind utility classes instead of inline styles.

Per coding guidelines, use Tailwind CSS for styling. Replace inline styles with utility classes.

           <i
             v-if="menuItem.showExternalIcon"
-            class="icon-[lucide--external-link] text-primary"
-            style="width: 16px; height: 16px; margin-left: auto"
+            class="icon-[lucide--external-link] text-primary w-4 h-4 ml-auto"
           />
           <i
             v-if="menuItem.key === 'more'"
-            class="pi pi-chevron-right"
-            style="margin-left: auto"
+            class="pi pi-chevron-right ml-auto"
           />

466-490: Relative time strings are hardcoded in English.

The formatReleaseDate function returns hardcoded English strings like "1d ago", "2w ago", "now". Per coding guidelines, use vue-i18n for ALL user-facing strings.

Consider using a library like @vueuse/core's useTimeAgo or adding i18n keys for relative time formatting.

src/platform/updates/components/WhatsNewPopup.vue (1)

36-47: Consider using design system Button for footer actions.

The close button uses the Button component, but the footer action buttons use native <button> elements with custom styles. For consistency and easier maintenance, consider using the design system Button component with appropriate severity props (secondary, primary).

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 6a6dd61 and 11775ff.

📒 Files selected for processing (11)
  • browser_tests/tests/releaseNotifications.spec.ts (7 hunks)
  • packages/design-system/src/css/style.css (4 hunks)
  • src/components/helpcenter/HelpCenterMenuContent.vue (14 hunks)
  • src/locales/en/main.json (4 hunks)
  • src/platform/updates/components/ReleaseNotificationToast.stories.ts (1 hunks)
  • src/platform/updates/components/ReleaseNotificationToast.test.ts (1 hunks)
  • src/platform/updates/components/ReleaseNotificationToast.vue (4 hunks)
  • src/platform/updates/components/WhatsNewPopup.stories.ts (1 hunks)
  • src/platform/updates/components/WhatsNewPopup.test.ts (1 hunks)
  • src/platform/updates/components/WhatsNewPopup.vue (7 hunks)
  • tests-ui/tests/components/helpcenter/WhatsNewPopup.test.ts (0 hunks)
💤 Files with no reviewable changes (1)
  • tests-ui/tests/components/helpcenter/WhatsNewPopup.test.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/platform/updates/components/ReleaseNotificationToast.test.ts
🧰 Additional context used
📓 Path-based instructions (22)
**/*.{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/platform/updates/components/ReleaseNotificationToast.stories.ts
  • src/components/helpcenter/HelpCenterMenuContent.vue
  • src/platform/updates/components/ReleaseNotificationToast.vue
  • browser_tests/tests/releaseNotifications.spec.ts
  • src/platform/updates/components/WhatsNewPopup.stories.ts
  • src/platform/updates/components/WhatsNewPopup.test.ts
  • src/platform/updates/components/WhatsNewPopup.vue
**/*.{ts,tsx,js}

📄 CodeRabbit inference engine (.cursorrules)

Use es-toolkit for utility functions

Files:

  • src/platform/updates/components/ReleaseNotificationToast.stories.ts
  • browser_tests/tests/releaseNotifications.spec.ts
  • src/platform/updates/components/WhatsNewPopup.stories.ts
  • src/platform/updates/components/WhatsNewPopup.test.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/platform/updates/components/ReleaseNotificationToast.stories.ts
  • browser_tests/tests/releaseNotifications.spec.ts
  • src/platform/updates/components/WhatsNewPopup.stories.ts
  • src/platform/updates/components/WhatsNewPopup.test.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/platform/updates/components/ReleaseNotificationToast.stories.ts
  • src/components/helpcenter/HelpCenterMenuContent.vue
  • src/platform/updates/components/ReleaseNotificationToast.vue
  • browser_tests/tests/releaseNotifications.spec.ts
  • src/platform/updates/components/WhatsNewPopup.stories.ts
  • src/platform/updates/components/WhatsNewPopup.test.ts
  • src/platform/updates/components/WhatsNewPopup.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/platform/updates/components/ReleaseNotificationToast.stories.ts
  • src/components/helpcenter/HelpCenterMenuContent.vue
  • src/platform/updates/components/ReleaseNotificationToast.vue
  • src/platform/updates/components/WhatsNewPopup.stories.ts
  • src/platform/updates/components/WhatsNewPopup.test.ts
  • src/platform/updates/components/WhatsNewPopup.vue
src/**/*.ts

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

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

Files:

  • src/platform/updates/components/ReleaseNotificationToast.stories.ts
  • src/platform/updates/components/WhatsNewPopup.stories.ts
  • src/platform/updates/components/WhatsNewPopup.test.ts
**/*.{ts,tsx,js,jsx,vue}

📄 CodeRabbit inference engine (CLAUDE.md)

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

Files:

  • src/platform/updates/components/ReleaseNotificationToast.stories.ts
  • src/components/helpcenter/HelpCenterMenuContent.vue
  • src/platform/updates/components/ReleaseNotificationToast.vue
  • browser_tests/tests/releaseNotifications.spec.ts
  • src/platform/updates/components/WhatsNewPopup.stories.ts
  • src/platform/updates/components/WhatsNewPopup.test.ts
  • src/platform/updates/components/WhatsNewPopup.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:

  • src/platform/updates/components/ReleaseNotificationToast.stories.ts
  • src/components/helpcenter/HelpCenterMenuContent.vue
  • src/platform/updates/components/ReleaseNotificationToast.vue
  • browser_tests/tests/releaseNotifications.spec.ts
  • src/platform/updates/components/WhatsNewPopup.stories.ts
  • src/platform/updates/components/WhatsNewPopup.test.ts
  • src/platform/updates/components/WhatsNewPopup.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:

  • src/platform/updates/components/ReleaseNotificationToast.stories.ts
  • browser_tests/tests/releaseNotifications.spec.ts
  • src/platform/updates/components/WhatsNewPopup.stories.ts
  • src/platform/updates/components/WhatsNewPopup.test.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/platform/updates/components/ReleaseNotificationToast.stories.ts
  • src/components/helpcenter/HelpCenterMenuContent.vue
  • src/platform/updates/components/ReleaseNotificationToast.vue
  • src/platform/updates/components/WhatsNewPopup.stories.ts
  • src/platform/updates/components/WhatsNewPopup.test.ts
  • src/platform/updates/components/WhatsNewPopup.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/platform/updates/components/ReleaseNotificationToast.stories.ts
  • src/components/helpcenter/HelpCenterMenuContent.vue
  • src/platform/updates/components/ReleaseNotificationToast.vue
  • src/platform/updates/components/WhatsNewPopup.stories.ts
  • src/platform/updates/components/WhatsNewPopup.test.ts
  • src/platform/updates/components/WhatsNewPopup.vue
src/**/*.{vue,ts,tsx}

📄 CodeRabbit inference engine (src/CLAUDE.md)

Follow Vue 3 composition API style guide

Files:

  • src/platform/updates/components/ReleaseNotificationToast.stories.ts
  • src/components/helpcenter/HelpCenterMenuContent.vue
  • src/platform/updates/components/ReleaseNotificationToast.vue
  • src/platform/updates/components/WhatsNewPopup.stories.ts
  • src/platform/updates/components/WhatsNewPopup.test.ts
  • src/platform/updates/components/WhatsNewPopup.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/platform/updates/components/ReleaseNotificationToast.stories.ts
  • src/components/helpcenter/HelpCenterMenuContent.vue
  • src/platform/updates/components/ReleaseNotificationToast.vue
  • src/platform/updates/components/WhatsNewPopup.stories.ts
  • src/platform/updates/components/WhatsNewPopup.test.ts
  • src/platform/updates/components/WhatsNewPopup.vue
**/*.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/components/helpcenter/HelpCenterMenuContent.vue
  • src/platform/updates/components/ReleaseNotificationToast.vue
  • src/platform/updates/components/WhatsNewPopup.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/components/helpcenter/HelpCenterMenuContent.vue
  • src/platform/updates/components/ReleaseNotificationToast.vue
  • src/platform/updates/components/WhatsNewPopup.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/components/helpcenter/HelpCenterMenuContent.vue
  • src/platform/updates/components/ReleaseNotificationToast.vue
  • src/platform/updates/components/WhatsNewPopup.vue
src/components/**/*.vue

📄 CodeRabbit inference engine (src/components/CLAUDE.md)

src/components/**/*.vue: Use setup() function in Vue 3 Composition API
Destructure props using Vue 3.5 style in Vue components
Use ref/reactive for state management in Vue 3 Composition API
Implement computed() for derived state in Vue 3 Composition API
Use provide/inject for dependency injection in Vue components
Prefer emit/@event-name for state changes over other communication patterns
Use defineExpose only for imperative operations (such as form.validate(), modal.open())
Replace PrimeVue Dropdown component with Select
Replace PrimeVue OverlayPanel component with Popover
Replace PrimeVue Calendar component with DatePicker
Replace PrimeVue InputSwitch component with ToggleSwitch
Replace PrimeVue Sidebar component with Drawer
Replace PrimeVue Chips component with AutoComplete with multiple enabled
Replace PrimeVue TabMenu component with Tabs without panels
Replace PrimeVue Steps component with Stepper without panels
Replace PrimeVue InlineMessage component with Message
Extract complex conditionals to computed properties
Implement cleanup for async operations in Vue components
Use lifecycle hooks: onMounted, onUpdated in Vue 3 Composition API
Use Teleport/Suspense when needed for component rendering
Define proper props and emits definitions in Vue components

Files:

  • src/components/helpcenter/HelpCenterMenuContent.vue
src/components/**/*.{vue,css}

📄 CodeRabbit inference engine (src/components/CLAUDE.md)

src/components/**/*.{vue,css}: Use Tailwind CSS only for styling (no custom CSS)
Use the correct tokens from style.css in the design system package

Files:

  • src/components/helpcenter/HelpCenterMenuContent.vue
src/components/**/*.{vue,ts,js}

📄 CodeRabbit inference engine (src/components/CLAUDE.md)

src/components/**/*.{vue,ts,js}: Use existing VueUse composables (such as useElementHover) instead of manually managing event listeners
Use useIntersectionObserver for visibility detection instead of custom scroll handlers
Use vue-i18n for ALL UI strings

Files:

  • src/components/helpcenter/HelpCenterMenuContent.vue
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/releaseNotifications.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/releaseNotifications.spec.ts
  • src/platform/updates/components/WhatsNewPopup.test.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/releaseNotifications.spec.ts
🧠 Learnings (46)
📓 Common learnings
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-11-24T19:48:23.088Z
Learning: Pull requests must include a clear description, linked issues in the format `- Fixes #123`, and screenshots/GIFs for UI changes
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
📚 Learning: 2025-11-24T19:47:34.324Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:34.324Z
Learning: Applies to src/**/*.{ts,tsx,vue} : Sanitize HTML with DOMPurify to prevent XSS attacks

Applied to files:

  • src/components/helpcenter/HelpCenterMenuContent.vue
  • src/platform/updates/components/ReleaseNotificationToast.vue
  • src/platform/updates/components/WhatsNewPopup.vue
📚 Learning: 2025-11-24T19:47:14.779Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:14.779Z
Learning: Applies to **/*.vue : Never use `:class="[]"` to merge class names - always use `import { cn } from '@/utils/tailwindUtil'` for class merging in Vue templates

Applied to files:

  • src/components/helpcenter/HelpCenterMenuContent.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 : Use Tailwind CSS for styling

Applied to files:

  • src/components/helpcenter/HelpCenterMenuContent.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 Tailwind CSS for styling Vue components

Applied to files:

  • src/components/helpcenter/HelpCenterMenuContent.vue
📚 Learning: 2025-12-01T23:45:28.610Z
Learnt from: DrJKL
Repo: Comfy-Org/ComfyUI_frontend PR: 7084
File: src/renderer/extensions/vueNodes/components/SlotConnectionDot.vue:23-26
Timestamp: 2025-12-01T23:45:28.610Z
Learning: Tailwind CSS supports arbitrary fractional width utilities beyond the common predefined ones. For example, `w-5/2` is valid syntax that represents 250% width (5÷2 = 2.5 = 250%). This applies to all utility variants including pseudo-elements like `after:w-5/2`.

Applied to files:

  • src/components/helpcenter/HelpCenterMenuContent.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 responsive design with Tailwind CSS

Applied to files:

  • src/components/helpcenter/HelpCenterMenuContent.vue
📚 Learning: 2025-12-01T23:42:30.894Z
Learnt from: DrJKL
Repo: Comfy-Org/ComfyUI_frontend PR: 7084
File: src/renderer/extensions/vueNodes/components/SlotConnectionDot.vue:23-26
Timestamp: 2025-12-01T23:42:30.894Z
Learning: In the ComfyUI frontend codebase, Tailwind CSS is configured with Preflight enabled (default), which automatically provides `content: ''` for pseudo-elements when using `after:` or `before:` variants - no need to explicitly add `after:content-['']`.

Applied to files:

  • src/components/helpcenter/HelpCenterMenuContent.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,css} : Use Tailwind CSS only for styling (no custom CSS)

Applied to files:

  • src/components/helpcenter/HelpCenterMenuContent.vue
📚 Learning: 2025-11-24T19:47:34.324Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: src/CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:34.324Z
Learning: Applies to src/**/{components,composables}/**/*.{ts,tsx,vue} : Use vue-i18n for ALL user-facing strings by adding them to `src/locales/en/main.json`

Applied to files:

  • src/components/helpcenter/HelpCenterMenuContent.vue
  • src/platform/updates/components/ReleaseNotificationToast.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,ts,js} : Use vue-i18n for ALL UI strings

Applied to files:

  • src/components/helpcenter/HelpCenterMenuContent.vue
  • src/platform/updates/components/ReleaseNotificationToast.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} : Use vue-i18n in Composition API for any string literals and place new translation entries in src/locales/en/main.json

Applied to files:

  • src/components/helpcenter/HelpCenterMenuContent.vue
  • src/platform/updates/components/ReleaseNotificationToast.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,ts} : Use vue-i18n in composition API for any string literals. Place new translation entries in src/locales/en/main.json

Applied to files:

  • src/components/helpcenter/HelpCenterMenuContent.vue
  • src/platform/updates/components/ReleaseNotificationToast.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 TabMenu component with Tabs without panels

Applied to files:

  • src/components/helpcenter/HelpCenterMenuContent.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 InputSwitch component with ToggleSwitch

Applied to files:

  • src/components/helpcenter/HelpCenterMenuContent.vue
  • src/platform/updates/components/WhatsNewPopup.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 InlineMessage component with Message

Applied to files:

  • src/components/helpcenter/HelpCenterMenuContent.vue
  • src/platform/updates/components/WhatsNewPopup.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 : Utilize ref and reactive for reactive state in Vue 3

Applied to files:

  • src/components/helpcenter/HelpCenterMenuContent.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/components/helpcenter/HelpCenterMenuContent.vue
  • src/platform/updates/components/WhatsNewPopup.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 Calendar component with DatePicker

Applied to files:

  • src/components/helpcenter/HelpCenterMenuContent.vue
  • src/platform/updates/components/WhatsNewPopup.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/components/helpcenter/HelpCenterMenuContent.vue
  • src/platform/updates/components/WhatsNewPopup.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 ref/reactive for state management in Vue 3 Composition API

Applied to files:

  • src/components/helpcenter/HelpCenterMenuContent.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/components/helpcenter/HelpCenterMenuContent.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 : 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:

  • src/components/helpcenter/HelpCenterMenuContent.vue
  • src/platform/updates/components/WhatsNewPopup.vue
📚 Learning: 2025-11-24T19:47:14.779Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:14.779Z
Learning: Applies to **/*.{ts,tsx,vue} : Use `const settingStore = useSettingStore()` and `settingStore.get('Comfy.SomeSetting')` to retrieve settings in TypeScript/Vue files

Applied to files:

  • src/components/helpcenter/HelpCenterMenuContent.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 lifecycle hooks: onMounted, onUpdated in Vue 3 Composition API

Applied to files:

  • src/components/helpcenter/HelpCenterMenuContent.vue
📚 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/tests/releaseNotifications.spec.ts
📚 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/tests/releaseNotifications.spec.ts
  • src/platform/updates/components/WhatsNewPopup.test.ts
📚 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/releaseNotifications.spec.ts
  • src/platform/updates/components/WhatsNewPopup.test.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} : Follow naming conventions for browser tests

Applied to files:

  • browser_tests/tests/releaseNotifications.spec.ts
📚 Learning: 2025-11-24T19:48:23.088Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-11-24T19:48:23.088Z
Learning: Applies to browser_tests/**/*.{test,spec}.ts : Playwright E2E tests can use optional tags like `mobile` and `2x` which are respected by the Playwright configuration

Applied to files:

  • browser_tests/tests/releaseNotifications.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} : Test user workflows in browser tests

Applied to files:

  • browser_tests/tests/releaseNotifications.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: Create browser tests as appropriate after code changes

Applied to files:

  • browser_tests/tests/releaseNotifications.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} : Check assets/ directory for test data when writing tests

Applied to files:

  • browser_tests/tests/releaseNotifications.spec.ts
📚 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} : Use existing test utilities rather than writing custom utilities

Applied to files:

  • browser_tests/tests/releaseNotifications.spec.ts
  • src/platform/updates/components/WhatsNewPopup.test.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} : Test across multiple viewports

Applied to files:

  • browser_tests/tests/releaseNotifications.spec.ts
  • src/platform/updates/components/WhatsNewPopup.test.ts
📚 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: Check tests-ui/README.md for test guidelines

Applied to files:

  • browser_tests/tests/releaseNotifications.spec.ts
  • src/platform/updates/components/WhatsNewPopup.test.ts
📚 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,css} : Use the correct tokens from style.css in the design system package

Applied to files:

  • packages/design-system/src/css/style.css
  • src/platform/updates/components/WhatsNewPopup.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} : Mock external dependencies in tests

Applied to files:

  • src/platform/updates/components/WhatsNewPopup.test.ts
📚 Learning: 2025-11-24T19:48:09.318Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: .cursor/rules/unit-test.mdc:0-0
Timestamp: 2025-11-24T19:48:09.318Z
Learning: Applies to test/**/*.{test,spec}.{js,ts,jsx,tsx} : Mocks should be cleanly written and easy to understand, with reusable mocks where possible

Applied to files:

  • src/platform/updates/components/WhatsNewPopup.test.ts
📚 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} : Always prefer vitest mock functions over writing verbose manual mocks

Applied to files:

  • src/platform/updates/components/WhatsNewPopup.test.ts
📚 Learning: 2025-11-24T19:48:23.088Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-11-24T19:48:23.088Z
Learning: Use Vitest (with happy-dom) for unit and component tests, and Playwright for E2E tests

Applied to files:

  • src/platform/updates/components/WhatsNewPopup.test.ts
📚 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 OverlayPanel component with Popover

Applied to files:

  • src/platform/updates/components/WhatsNewPopup.test.ts
  • src/platform/updates/components/WhatsNewPopup.vue
📚 Learning: 2025-11-24T19:47:14.779Z
Learnt from: CR
Repo: Comfy-Org/ComfyUI_frontend PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-24T19:47:14.779Z
Learning: Applies to **/*.{vue,html} : Never use `dark:` or `dark-theme:` Tailwind variants - instead use semantic values from `style.css` theme, e.g. `bg-node-component-surface`

Applied to files:

  • src/platform/updates/components/WhatsNewPopup.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 Dropdown component with Select

Applied to files:

  • src/platform/updates/components/WhatsNewPopup.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 Sidebar component with Drawer

Applied to files:

  • src/platform/updates/components/WhatsNewPopup.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 defineExpose only for imperative operations (such as form.validate(), modal.open())

Applied to files:

  • src/platform/updates/components/WhatsNewPopup.vue
🧬 Code graph analysis (2)
src/platform/updates/components/WhatsNewPopup.stories.ts (3)
src/platform/updates/common/releaseService.ts (1)
  • ReleaseNote (10-10)
src/platform/updates/common/releaseStore.ts (1)
  • useReleaseStore (16-291)
src/platform/updates/components/ReleaseNotificationToast.stories.ts (5)
  • Default (126-130)
  • WithImage (132-136)
  • MajorRelease (138-142)
  • LongContent (144-166)
  • EmptyContent (168-179)
src/platform/updates/components/WhatsNewPopup.test.ts (1)
src/platform/updates/common/releaseService.ts (1)
  • ReleaseNote (10-10)
🔇 Additional comments (21)
browser_tests/tests/releaseNotifications.spec.ts (1)

53-53: Good migration to data-testid selectors.

Switching from CSS class selectors (.whats-new-section) to getByTestId('whats-new-section') is a best practice for E2E tests. This makes tests more resilient to styling refactors and aligns with Playwright's recommended selector strategy.

Also applies to: 82-82, 128-128, 178-178, 266-266, 314-314, 365-365

src/platform/updates/components/WhatsNewPopup.test.ts (1)

64-92: Good test setup with proper mocking patterns.

The test structure follows Vitest best practices with clear mock setup, beforeEach cleanup, and a reusable mountComponent helper. The PrimeVue and icon stubbing approach is appropriate for unit testing Vue components.

packages/design-system/src/css/style.css (2)

188-189: New menu tokens are well-structured and consistent.

The --interface-menu-surface and --interface-menu-stroke tokens follow the established naming conventions and provide appropriate values for both light and dark themes. The color choices (white/smoke-600 for light, charcoal-800/ash-800 for dark) maintain good contrast ratios.

Also applies to: 310-311


427-428: Token aliases properly configured in @theme inline.

The color token aliases correctly reference the base tokens, enabling Tailwind utility class usage (e.g., bg-interface-menu-surface).

src/locales/en/main.json (3)

749-752: Localization keys properly updated for Help Center menu.

The new feedback and renamed help keys align with the component changes in HelpCenterMenuContent.vue.


766-770: Release toast strings updated with user-friendly copy.

The updated strings ("New update is out!", "See what's new") are more conversational and appropriate for a toast notification. The new description key provides fallback content when release notes are empty.


2251-2255: New help section keys added for accessibility.

The help.recentReleases and help.helpCenterMenu keys properly support the aria-label attributes in the components, addressing the i18n requirements for accessibility text.

src/platform/updates/components/ReleaseNotificationToast.stories.ts (1)

8-67: Good mock data coverage for different release scenarios.

The mock releases cover essential edge cases: standard release, release with image, major release, and the stories include LongContent and EmptyContent variants. This provides comprehensive visual testing coverage.

src/platform/updates/components/ReleaseNotificationToast.vue (4)

106-136: Good XSS protection and i18n usage.

The formattedContent computed properly sanitizes all HTML output with DOMPurify, including the fallback content. The i18n t() function is correctly used for user-facing strings. This addresses the previous review concerns.


218-219: CSS selector has unnecessary comma before newline.

The selector .sidebar-left, followed by .sidebar-left.small-sidebar on line 219 is correct, but the formatting could be cleaner.


3-63: Well-structured card layout with proper semantic tokens.

The template uses semantic color tokens (bg-base-background, border-border-default, text-base-foreground, text-muted-foreground) consistently. The layout follows a clear hierarchy with proper accessibility considerations.


199-205: Good use of defineExpose for testing.

Exposing handleSkip, handleLearnMore, and handleUpdate enables unit tests to trigger these handlers directly, which is appropriate for component testing.

src/components/helpcenter/HelpCenterMenuContent.vue (3)

295-315: Feedback and Help buttons have identical actions.

Both menu items call commandStore.execute('Comfy.ContactSupport') and track the same event 'help_feedback'. Is this intentional, or should they have distinct functionality?


3-5: Past review issues addressed - aria-labels now use i18n.

The aria-labels for "Help Center Menu" and "Recent releases" now properly use $t('help.helpCenterMenu') and $t('help.recentReleases') respectively.

Also applies to: 99-102


573-584: Good use of new semantic design tokens.

The component correctly uses the new --interface-menu-surface and --interface-menu-stroke tokens for consistent theming, enabling automatic light/dark mode support.

src/platform/updates/components/WhatsNewPopup.vue (3)

97-133: LGTM on content sanitization and error handling.

The formattedContent computed correctly uses DOMPurify for HTML sanitization with proper fallback handling for edge cases (empty content, parse errors). The comment at line 123 correctly notes that renderMarkdownToHtml already sanitizes.


152-158: LGTM on CTA handler implementation.

The handleCTA correctly opens the update documentation URL and then closes the popup to mark the release as seen.


187-197: Good migration to semantic design tokens.

The CSS correctly uses semantic tokens like --interface-menu-surface and --interface-menu-stroke instead of hardcoded colors, enabling proper light/dark theme support as intended by this PR.

src/platform/updates/components/WhatsNewPopup.stories.ts (3)

86-117: LGTM on Storybook decorator setup.

The decorator correctly initializes the store with mock data for each story. Using Object.defineProperty to override computed properties is a pragmatic approach for Storybook visualization, even though it breaks reactivity—this is acceptable since stories only need static display.


123-211: Good story coverage for content scenarios.

The stories cover key rendering scenarios: default content, image-first content, major releases, long content scrolling, minimal content, and empty content (testing the "No release notes available" fallback). This aligns well with the component's formattedContent logic.


8-67: Mock data looks good with realistic content.

The mock releases provide representative content for testing different UI states. Note that the Unsplash image URLs rely on external resources; if network isolation is needed for Storybook, consider using local placeholder images.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:design-system area:system-notification size:XXL This PR changes 1000+ lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants