refactor: migrate PrimeVue Chip to custom Tag component#10673
refactor: migrate PrimeVue Chip to custom Tag component#10673dante01yoon wants to merge 11 commits intomainfrom
Conversation
Add Tag component with CVA variants matching Figma design system: - square (rounded-sm) and rounded (pill) shapes - removable state with X close button - icon slot support Rename SquareChip to Tag across all consumers and stories. Includes unit tests (5 tests) covering rendering, removable behavior, and icon slot.
Replace custom overlay variant with Figma-defined states: - default: full opacity, foreground text - unselected: opacity-70, muted-foreground text - selected: full opacity with remove button (via removable prop) Hover state handled via CSS :hover, not a prop.
Add overlay shape (bg-zinc-500/40, text-white/90) for tags that sit on top of image thumbnails. Used in SampleModelSelector. Pending Figma design system confirmation.
- SearchFilterChip: PrimeVue Chip+Badge → Tag (removable) + Badge
- NodeSearchItem: PrimeVue Chip → Tag (aliased as ChipTag to avoid
name collision with PrimeVue Tag, which migrates in a follow-up PR)
- DownloadItem: PrimeVue Chip (removable) → Tag (removable)
- Update E2E selectors from .p-chip-remove-icon to accessible
getByRole('button', { name: 'Remove' })
🎭 Playwright: ✅ 770 passed, 0 failed · 2 flaky📊 Browser Reports
|
🎨 Storybook: ✅ Built — View Storybook |
📝 WalkthroughWalkthroughThis PR replaces PrimeVue Changes
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
SearchFilterChip (5 tests): badge rendering, semantic class mapping, remove event, fallback class. DownloadItem (4 tests): cancelled/error tag display, remove button, in-progress state, file path label.
📦 Bundle: 5.09 MB gzip 🔴 +79 BDetailsSummary
Category Glance App Entry Points — 22.3 kB (baseline 22.3 kB) • ⚪ 0 BMain entry bundles and manifests
Status: 1 added / 1 removed Graph Workspace — 1.14 MB (baseline 1.14 MB) • 🟢 -76 BGraph editor runtime, canvas, workflow orchestration
Status: 1 added / 1 removed Views & Navigation — 76.6 kB (baseline 76.6 kB) • ⚪ 0 BTop-level views, pages, and routed surfaces
Status: 9 added / 9 removed / 2 unchanged Panels & Settings — 484 kB (baseline 484 kB) • ⚪ 0 BConfiguration panels, inspectors, and settings screens
Status: 10 added / 10 removed / 12 unchanged User & Accounts — 17.1 kB (baseline 17.1 kB) • ⚪ 0 BAuthentication, profile, and account management bundles
Status: 6 added / 6 removed / 1 unchanged Editors & Dialogs — 109 kB (baseline 109 kB) • ⚪ 0 BModals, dialogs, drawers, and in-app editors
Status: 2 added / 2 removed UI Components — 60.3 kB (baseline 60.3 kB) • ⚪ 0 BReusable component library chunks
Status: 8 added / 8 removed / 5 unchanged Data & Services — 2.96 MB (baseline 2.96 MB) • 🔴 +1.1 kBStores, services, APIs, and repositories
Status: 13 added / 13 removed / 4 unchanged Utilities & Hooks — 334 kB (baseline 334 kB) • ⚪ 0 BHelpers, composables, and utility bundles
Status: 16 added / 16 removed / 9 unchanged Vendor & Third-Party — 9.8 MB (baseline 9.8 MB) • 🟢 -17 BExternal libraries and shared vendor chunks
Status: 1 added / 1 removed / 15 unchanged Other — 8.45 MB (baseline 8.45 MB) • ⚪ 0 BBundles that do not match a named category
Status: 66 added / 66 removed / 68 unchanged ⚡ Performance Report
No regressions detected. All metrics
Historical variance (last 15 runs)
Trend (last 15 commits on main)
Raw data{
"timestamp": "2026-03-29T07:45:12.698Z",
"gitSha": "93ac24ffd6957c7f13ab334eb23085f07a1a1c34",
"branch": "feature/migrate-primevue-chip",
"measurements": [
{
"name": "canvas-idle",
"durationMs": 2032.2809999999834,
"styleRecalcs": 12,
"styleRecalcDurationMs": 11.863999999999999,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 370.87,
"heapDeltaBytes": 10994812,
"heapUsedBytes": 62849740,
"domNodes": 24,
"jsHeapTotalBytes": 25952256,
"scriptDurationMs": 23.743,
"eventListeners": 6,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.700000000000728
},
{
"name": "canvas-idle",
"durationMs": 2022.467000000006,
"styleRecalcs": 11,
"styleRecalcDurationMs": 9.049,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 344.258,
"heapDeltaBytes": 20409928,
"heapUsedBytes": 63144492,
"domNodes": 22,
"jsHeapTotalBytes": 23068672,
"scriptDurationMs": 21.003,
"eventListeners": 6,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.700000000000728
},
{
"name": "canvas-idle",
"durationMs": 2014.3269999999802,
"styleRecalcs": 12,
"styleRecalcDurationMs": 10.218,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 347.58900000000006,
"heapDeltaBytes": 20372968,
"heapUsedBytes": 62862848,
"domNodes": 24,
"jsHeapTotalBytes": 22544384,
"scriptDurationMs": 23.215,
"eventListeners": 6,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.700000000000728
},
{
"name": "canvas-mouse-sweep",
"durationMs": 2003.4280000000138,
"styleRecalcs": 81,
"styleRecalcDurationMs": 42.75,
"layouts": 12,
"layoutDurationMs": 3.5300000000000002,
"taskDurationMs": 928.5439999999999,
"heapDeltaBytes": 16724312,
"heapUsedBytes": 59186304,
"domNodes": 67,
"jsHeapTotalBytes": 23068672,
"scriptDurationMs": 134.497,
"eventListeners": 6,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.670000000000012,
"p95FrameDurationMs": 16.800000000000182
},
{
"name": "canvas-mouse-sweep",
"durationMs": 1990.3039999999805,
"styleRecalcs": 81,
"styleRecalcDurationMs": 40.483000000000004,
"layouts": 12,
"layoutDurationMs": 3.3,
"taskDurationMs": 919.719,
"heapDeltaBytes": 15983496,
"heapUsedBytes": 58768436,
"domNodes": 66,
"jsHeapTotalBytes": 23330816,
"scriptDurationMs": 130.368,
"eventListeners": 6,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.700000000000728
},
{
"name": "canvas-mouse-sweep",
"durationMs": 1764.4510000000082,
"styleRecalcs": 75,
"styleRecalcDurationMs": 36.573,
"layouts": 12,
"layoutDurationMs": 3.601,
"taskDurationMs": 719.446,
"heapDeltaBytes": 15840416,
"heapUsedBytes": 58269148,
"domNodes": 59,
"jsHeapTotalBytes": 22806528,
"scriptDurationMs": 130.126,
"eventListeners": 4,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.670000000000012,
"p95FrameDurationMs": 16.800000000000182
},
{
"name": "canvas-zoom-sweep",
"durationMs": 1727.9219999999782,
"styleRecalcs": 32,
"styleRecalcDurationMs": 17.738,
"layouts": 6,
"layoutDurationMs": 0.7290000000000001,
"taskDurationMs": 284.28000000000003,
"heapDeltaBytes": 24677984,
"heapUsedBytes": 67379232,
"domNodes": 78,
"jsHeapTotalBytes": 20185088,
"scriptDurationMs": 24.549999999999997,
"eventListeners": 19,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.800000000000182
},
{
"name": "canvas-zoom-sweep",
"durationMs": 1733.7559999999712,
"styleRecalcs": 32,
"styleRecalcDurationMs": 16.267000000000003,
"layouts": 6,
"layoutDurationMs": 0.573,
"taskDurationMs": 282.951,
"heapDeltaBytes": 24730012,
"heapUsedBytes": 67128228,
"domNodes": 79,
"jsHeapTotalBytes": 19660800,
"scriptDurationMs": 22.195000000000007,
"eventListeners": 19,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.66333333333335,
"p95FrameDurationMs": 16.799999999999272
},
{
"name": "canvas-zoom-sweep",
"durationMs": 1728.40199999996,
"styleRecalcs": 31,
"styleRecalcDurationMs": 16.802999999999997,
"layouts": 6,
"layoutDurationMs": 0.598,
"taskDurationMs": 283.671,
"heapDeltaBytes": 24630696,
"heapUsedBytes": 67113280,
"domNodes": 79,
"jsHeapTotalBytes": 20185088,
"scriptDurationMs": 22.197000000000003,
"eventListeners": 19,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.66333333333332,
"p95FrameDurationMs": 16.700000000000728
},
{
"name": "dom-widget-clipping",
"durationMs": 558.3409999999844,
"styleRecalcs": 13,
"styleRecalcDurationMs": 9.377,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 343.798,
"heapDeltaBytes": 6519612,
"heapUsedBytes": 49263332,
"domNodes": 22,
"jsHeapTotalBytes": 13107200,
"scriptDurationMs": 66.096,
"eventListeners": 2,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.800000000000182
},
{
"name": "dom-widget-clipping",
"durationMs": 533.1739999999741,
"styleRecalcs": 13,
"styleRecalcDurationMs": 9.469,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 327.201,
"heapDeltaBytes": 6541948,
"heapUsedBytes": 49267580,
"domNodes": 22,
"jsHeapTotalBytes": 13107200,
"scriptDurationMs": 64.95700000000001,
"eventListeners": 2,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.799999999999727
},
{
"name": "dom-widget-clipping",
"durationMs": 537.9759999999578,
"styleRecalcs": 13,
"styleRecalcDurationMs": 9.101999999999999,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 331.534,
"heapDeltaBytes": -2191736,
"heapUsedBytes": 50463904,
"domNodes": 21,
"jsHeapTotalBytes": 16252928,
"scriptDurationMs": 62.458000000000006,
"eventListeners": 2,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.700000000000273
},
{
"name": "large-graph-idle",
"durationMs": 2042.1049999999923,
"styleRecalcs": 10,
"styleRecalcDurationMs": 9.678000000000003,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 522.062,
"heapDeltaBytes": 5649772,
"heapUsedBytes": 56229492,
"domNodes": -258,
"jsHeapTotalBytes": 15929344,
"scriptDurationMs": 95.471,
"eventListeners": -127,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.66333333333335,
"p95FrameDurationMs": 16.699999999999818
},
{
"name": "large-graph-idle",
"durationMs": 2032.9310000000191,
"styleRecalcs": 9,
"styleRecalcDurationMs": 8.439000000000002,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 526.0050000000001,
"heapDeltaBytes": 4795524,
"heapUsedBytes": 55877296,
"domNodes": -259,
"jsHeapTotalBytes": 15667200,
"scriptDurationMs": 93.673,
"eventListeners": -125,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.800000000000182
},
{
"name": "large-graph-idle",
"durationMs": 2034.3729999999596,
"styleRecalcs": 11,
"styleRecalcDurationMs": 9.840000000000002,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 513.497,
"heapDeltaBytes": 3953020,
"heapUsedBytes": 55465008,
"domNodes": -258,
"jsHeapTotalBytes": 15929344,
"scriptDurationMs": 93.557,
"eventListeners": -125,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.699999999999818
},
{
"name": "large-graph-pan",
"durationMs": 2148.989999999998,
"styleRecalcs": 69,
"styleRecalcDurationMs": 15.861000000000004,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 1145.951,
"heapDeltaBytes": 21706620,
"heapUsedBytes": 74869076,
"domNodes": -259,
"jsHeapTotalBytes": 18231296,
"scriptDurationMs": 439.228,
"eventListeners": -125,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.66333333333332,
"p95FrameDurationMs": 16.800000000000182
},
{
"name": "large-graph-pan",
"durationMs": 2176.4539999999784,
"styleRecalcs": 70,
"styleRecalcDurationMs": 15.865000000000004,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 1093.878,
"heapDeltaBytes": 19146736,
"heapUsedBytes": 70925072,
"domNodes": -257,
"jsHeapTotalBytes": 17969152,
"scriptDurationMs": 414.768,
"eventListeners": -125,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.66999999999998,
"p95FrameDurationMs": 16.699999999999818
},
{
"name": "large-graph-pan",
"durationMs": 2106.8520000000035,
"styleRecalcs": 69,
"styleRecalcDurationMs": 16.342,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 1042.8359999999998,
"heapDeltaBytes": 14934528,
"heapUsedBytes": 68215284,
"domNodes": -260,
"jsHeapTotalBytes": 18231296,
"scriptDurationMs": 381.055,
"eventListeners": -125,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.66333333333335,
"p95FrameDurationMs": 16.700000000000728
},
{
"name": "large-graph-zoom",
"durationMs": 3129.784000000029,
"styleRecalcs": 66,
"styleRecalcDurationMs": 17.551000000000002,
"layouts": 60,
"layoutDurationMs": 7.367,
"taskDurationMs": 1321.899,
"heapDeltaBytes": 5385168,
"heapUsedBytes": 59662392,
"domNodes": -262,
"jsHeapTotalBytes": 18026496,
"scriptDurationMs": 486.651,
"eventListeners": -125,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.66333333333332,
"p95FrameDurationMs": 16.800000000000182
},
{
"name": "large-graph-zoom",
"durationMs": 3160.246000000029,
"styleRecalcs": 66,
"styleRecalcDurationMs": 16.369999999999997,
"layouts": 60,
"layoutDurationMs": 7.403,
"taskDurationMs": 1303.093,
"heapDeltaBytes": 7230248,
"heapUsedBytes": 61519076,
"domNodes": -262,
"jsHeapTotalBytes": 17764352,
"scriptDurationMs": 485.716,
"eventListeners": -125,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.66333333333335,
"p95FrameDurationMs": 16.799999999999272
},
{
"name": "large-graph-zoom",
"durationMs": 3134.636999999998,
"styleRecalcs": 65,
"styleRecalcDurationMs": 15.028,
"layouts": 60,
"layoutDurationMs": 7.295999999999999,
"taskDurationMs": 1288.422,
"heapDeltaBytes": 6446088,
"heapUsedBytes": 61641864,
"domNodes": -267,
"jsHeapTotalBytes": 17764352,
"scriptDurationMs": 481.4240000000001,
"eventListeners": -125,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.800000000000182
},
{
"name": "minimap-idle",
"durationMs": 2022.312999999997,
"styleRecalcs": 9,
"styleRecalcDurationMs": 8.064000000000002,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 511.0220000000001,
"heapDeltaBytes": 4174096,
"heapUsedBytes": 56414408,
"domNodes": -260,
"jsHeapTotalBytes": 16453632,
"scriptDurationMs": 94.888,
"eventListeners": -127,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.66333333333335,
"p95FrameDurationMs": 16.699999999999818
},
{
"name": "minimap-idle",
"durationMs": 2033.7349999999788,
"styleRecalcs": 10,
"styleRecalcDurationMs": 8.921000000000001,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 522.27,
"heapDeltaBytes": 4039152,
"heapUsedBytes": 56409640,
"domNodes": -258,
"jsHeapTotalBytes": 16191488,
"scriptDurationMs": 95.20100000000001,
"eventListeners": -125,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.700000000000728
},
{
"name": "minimap-idle",
"durationMs": 2048.9209999999503,
"styleRecalcs": 10,
"styleRecalcDurationMs": 8.944,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 520.978,
"heapDeltaBytes": 3330576,
"heapUsedBytes": 56395220,
"domNodes": -262,
"jsHeapTotalBytes": 16453632,
"scriptDurationMs": 90.14100000000002,
"eventListeners": -127,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.66333333333332,
"p95FrameDurationMs": 16.800000000000182
},
{
"name": "subgraph-dom-widget-clipping",
"durationMs": 534.0980000000286,
"styleRecalcs": 48,
"styleRecalcDurationMs": 11.875,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 338.89000000000004,
"heapDeltaBytes": 6404468,
"heapUsedBytes": 49489452,
"domNodes": 22,
"jsHeapTotalBytes": 13893632,
"scriptDurationMs": 117.66699999999999,
"eventListeners": 8,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.700000000000273
},
{
"name": "subgraph-dom-widget-clipping",
"durationMs": 528.0159999999796,
"styleRecalcs": 48,
"styleRecalcDurationMs": 11.616,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 345.001,
"heapDeltaBytes": 6177956,
"heapUsedBytes": 50468664,
"domNodes": 22,
"jsHeapTotalBytes": 12582912,
"scriptDurationMs": 124.38899999999998,
"eventListeners": 8,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.700000000000273
},
{
"name": "subgraph-dom-widget-clipping",
"durationMs": 547.5969999999961,
"styleRecalcs": 48,
"styleRecalcDurationMs": 11.618,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 349.47999999999996,
"heapDeltaBytes": 6433092,
"heapUsedBytes": 49637244,
"domNodes": 22,
"jsHeapTotalBytes": 13369344,
"scriptDurationMs": 125.07399999999998,
"eventListeners": 8,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.799999999999727
},
{
"name": "subgraph-idle",
"durationMs": 2040.2740000000108,
"styleRecalcs": 9,
"styleRecalcDurationMs": 8.588,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 366.16900000000004,
"heapDeltaBytes": 19789648,
"heapUsedBytes": 62909920,
"domNodes": 18,
"jsHeapTotalBytes": 22806528,
"scriptDurationMs": 12.336,
"eventListeners": 4,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.699999999999818
},
{
"name": "subgraph-idle",
"durationMs": 2004.287999999974,
"styleRecalcs": 12,
"styleRecalcDurationMs": 10.603,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 336.01000000000005,
"heapDeltaBytes": 19915216,
"heapUsedBytes": 62932772,
"domNodes": 23,
"jsHeapTotalBytes": 23592960,
"scriptDurationMs": 17.887,
"eventListeners": 6,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.800000000000182
},
{
"name": "subgraph-idle",
"durationMs": 1998.0820000000676,
"styleRecalcs": 12,
"styleRecalcDurationMs": 11.001999999999999,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 329.028,
"heapDeltaBytes": 19961908,
"heapUsedBytes": 62638488,
"domNodes": 24,
"jsHeapTotalBytes": 22806528,
"scriptDurationMs": 17.166999999999998,
"eventListeners": 6,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.700000000000728
},
{
"name": "subgraph-mouse-sweep",
"durationMs": 1999.808999999999,
"styleRecalcs": 84,
"styleRecalcDurationMs": 46.129,
"layouts": 16,
"layoutDurationMs": 4.3309999999999995,
"taskDurationMs": 917.672,
"heapDeltaBytes": 12187852,
"heapUsedBytes": 55167880,
"domNodes": 73,
"jsHeapTotalBytes": 23330816,
"scriptDurationMs": 100.57900000000001,
"eventListeners": 6,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.800000000000182
},
{
"name": "subgraph-mouse-sweep",
"durationMs": 1991.32400000002,
"styleRecalcs": 85,
"styleRecalcDurationMs": 41.23,
"layouts": 16,
"layoutDurationMs": 3.7809999999999997,
"taskDurationMs": 884.476,
"heapDeltaBytes": 11936324,
"heapUsedBytes": 54946916,
"domNodes": 74,
"jsHeapTotalBytes": 23068672,
"scriptDurationMs": 98.92600000000002,
"eventListeners": 6,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.700000000000728
},
{
"name": "subgraph-mouse-sweep",
"durationMs": 1978.9180000000215,
"styleRecalcs": 84,
"styleRecalcDurationMs": 45.05,
"layouts": 16,
"layoutDurationMs": 4.356999999999999,
"taskDurationMs": 884.043,
"heapDeltaBytes": 11836572,
"heapUsedBytes": 54899224,
"domNodes": 74,
"jsHeapTotalBytes": 23068672,
"scriptDurationMs": 100.22200000000001,
"eventListeners": 6,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.700000000000728
},
{
"name": "viewport-pan-sweep",
"durationMs": 8193.512999999995,
"styleRecalcs": 250,
"styleRecalcDurationMs": 43.728,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 3647.999,
"heapDeltaBytes": 26935448,
"heapUsedBytes": 78756328,
"domNodes": -256,
"jsHeapTotalBytes": 19308544,
"scriptDurationMs": 1246.839,
"eventListeners": -109,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.700000000000728
},
{
"name": "viewport-pan-sweep",
"durationMs": 8165.233,
"styleRecalcs": 251,
"styleRecalcDurationMs": 43.577,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 3602.351,
"heapDeltaBytes": 25318012,
"heapUsedBytes": 75649864,
"domNodes": -255,
"jsHeapTotalBytes": 20066304,
"scriptDurationMs": 1237.473,
"eventListeners": -111,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.799999999999272
},
{
"name": "viewport-pan-sweep",
"durationMs": 8138.403000000039,
"styleRecalcs": 251,
"styleRecalcDurationMs": 44.10600000000001,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 3673.754000000001,
"heapDeltaBytes": 18288128,
"heapUsedBytes": 68871400,
"domNodes": -254,
"jsHeapTotalBytes": 19804160,
"scriptDurationMs": 1266.301,
"eventListeners": -111,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.700000000000728
},
{
"name": "vue-large-graph-idle",
"durationMs": 12035.836000000018,
"styleRecalcs": 0,
"styleRecalcDurationMs": 0,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 12026.935000000001,
"heapDeltaBytes": -29515076,
"heapUsedBytes": 165315476,
"domNodes": -8331,
"jsHeapTotalBytes": 26042368,
"scriptDurationMs": 584.592,
"eventListeners": -16462,
"totalBlockingTimeMs": 0,
"frameDurationMs": 17.223333333333237,
"p95FrameDurationMs": 16.799999999999272
},
{
"name": "vue-large-graph-idle",
"durationMs": 12109.173999999995,
"styleRecalcs": 0,
"styleRecalcDurationMs": 0,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 12083.601999999999,
"heapDeltaBytes": -29051292,
"heapUsedBytes": 165452648,
"domNodes": -8331,
"jsHeapTotalBytes": 26828800,
"scriptDurationMs": 578.2040000000001,
"eventListeners": -16462,
"totalBlockingTimeMs": 0,
"frameDurationMs": 17.216666666666665,
"p95FrameDurationMs": 16.799999999999272
},
{
"name": "vue-large-graph-idle",
"durationMs": 11800.06000000003,
"styleRecalcs": 0,
"styleRecalcDurationMs": 0,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 11790.759,
"heapDeltaBytes": -29398652,
"heapUsedBytes": 165382192,
"domNodes": -8331,
"jsHeapTotalBytes": 26304512,
"scriptDurationMs": 576.234,
"eventListeners": -16464,
"totalBlockingTimeMs": 0,
"frameDurationMs": 17.219999999999953,
"p95FrameDurationMs": 16.80000000000291
},
{
"name": "vue-large-graph-pan",
"durationMs": 14072.186999999985,
"styleRecalcs": 66,
"styleRecalcDurationMs": 13.23900000000003,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 14042.403,
"heapDeltaBytes": -23920632,
"heapUsedBytes": 186995940,
"domNodes": -8331,
"jsHeapTotalBytes": 28053504,
"scriptDurationMs": 862.5039999999999,
"eventListeners": -16460,
"totalBlockingTimeMs": 0,
"frameDurationMs": 17.219999999999953,
"p95FrameDurationMs": 16.700000000000728
},
{
"name": "vue-large-graph-pan",
"durationMs": 14161.641999999973,
"styleRecalcs": 65,
"styleRecalcDurationMs": 13.690999999999981,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 14137.502000000002,
"heapDeltaBytes": -7985676,
"heapUsedBytes": 185730148,
"domNodes": -8331,
"jsHeapTotalBytes": 25694208,
"scriptDurationMs": 833.568,
"eventListeners": -16458,
"totalBlockingTimeMs": 0,
"frameDurationMs": 17.223333333333358,
"p95FrameDurationMs": 16.799999999999272
},
{
"name": "vue-large-graph-pan",
"durationMs": 14271.937999999976,
"styleRecalcs": 67,
"styleRecalcDurationMs": 13.699000000000016,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 14248.024999999998,
"heapDeltaBytes": -46016036,
"heapUsedBytes": 147809252,
"domNodes": -8331,
"jsHeapTotalBytes": -4628480,
"scriptDurationMs": 859.43,
"eventListeners": -16488,
"totalBlockingTimeMs": 0,
"frameDurationMs": 17.223333333333237,
"p95FrameDurationMs": 16.799999999999272
},
{
"name": "workflow-execution",
"durationMs": 441.41500000000633,
"styleRecalcs": 18,
"styleRecalcDurationMs": 22.831,
"layouts": 5,
"layoutDurationMs": 1.411,
"taskDurationMs": 119.554,
"heapDeltaBytes": 4710472,
"heapUsedBytes": 48977052,
"domNodes": 167,
"jsHeapTotalBytes": 0,
"scriptDurationMs": 28.158999999999995,
"eventListeners": 71,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.700000000000273
},
{
"name": "workflow-execution",
"durationMs": 450.37999999999556,
"styleRecalcs": 17,
"styleRecalcDurationMs": 21.554,
"layouts": 5,
"layoutDurationMs": 1.3139999999999998,
"taskDurationMs": 106.12700000000002,
"heapDeltaBytes": 4379500,
"heapUsedBytes": 48403860,
"domNodes": 156,
"jsHeapTotalBytes": 0,
"scriptDurationMs": 22.863000000000003,
"eventListeners": 71,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.663333333333338,
"p95FrameDurationMs": 16.700000000000273
},
{
"name": "workflow-execution",
"durationMs": 108.4569999999303,
"styleRecalcs": 8,
"styleRecalcDurationMs": 14.478,
"layouts": 4,
"layoutDurationMs": 1.2969999999999997,
"taskDurationMs": 78.838,
"heapDeltaBytes": 2486336,
"heapUsedBytes": 47057232,
"domNodes": 142,
"jsHeapTotalBytes": 0,
"scriptDurationMs": 19.590000000000003,
"eventListeners": 19,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.663333333333338,
"p95FrameDurationMs": 16.700000000000273
}
]
} |
) ## Summary - Add `Tag` component based on Figma design system with CVA variants - `square` (rounded-sm) and `rounded` (pill) shapes - `overlay` shape for tags on image thumbnails (pending Figma confirmation) - `default`, `unselected`, `selected` states matching Figma - `removable` prop with X close button and `remove` event - Icon slot support - Rename `SquareChip` → `Tag` across all consumers (WorkflowTemplateSelectorDialog, SampleModelSelector) - Update all Storybook stories (Tag, Card, BaseModalLayout) - Delete old `SquareChip.vue` and `SquareChip.stories.ts` - Add E2E screenshot test for template card overlay tags Foundation for migrating PrimeVue `Chip` and `Tag` components in follow-up PRs. ## Test plan - [x] Unit tests pass (5 tests: rendering, removable, icon slot) - [x] E2E screenshot test: template cards with overlay tags - [x] Typecheck passes - [x] Lint passes - [ ] Verify Tag stories render correctly in Storybook - [ ] Verify WorkflowTemplateSelectorDialog tags display correctly - [ ] Verify SampleModelSelector chips display correctly ## Follow-up work - **PR 4** (#10673): Migrate PrimeVue `Chip` → custom `Tag` (SearchFilterChip, NodeSearchItem, DownloadItem) - **PR 5** (planned): Migrate PrimeVue `Tag` → custom `Tag` (~14 files)
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@src/components/common/SearchFilterChip.test.ts`:
- Around line 31-35: The test currently asserts Tailwind utility classes
(expect(badge.className).toContain('bg-green-500')) which is brittle; update the
tests that use renderChip (the "applies semantic badge class for input type"
test and the others flagged) to assert semantic behavior instead — e.g., check
the badge element exists, its text content/accessible name is 'I' and that it
has the semantic prop/class passed in (badgeClass like 'i-badge') or use
toHaveAttribute/toHaveClass with only non-utility class names, rather than
checking for Tailwind utility classes; locate the checks in the tests
referencing renderChip and replace utility-class assertions with these semantic
assertions.
In `@src/components/sidebar/tabs/modelLibrary/DownloadItem.vue`:
- Around line 6-9: The template currently treats both 'cancelled' and 'error'
statuses the same and always renders the cancelled label; update the conditional
rendering around the Tag (where download.status is checked) to use a
status-specific label: render t('electronFileDownload.cancelled') when
download.status === 'cancelled' and render t('electronFileDownload.error') (or
the appropriate error translation key) when download.status === 'error', keeping
the same Tag component and styling logic so users see the correct label for each
status.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 08323b0a-c618-476f-afd3-ea126cde4bed
📒 Files selected for processing (7)
browser_tests/fixtures/components/ComfyNodeSearchBox.tsbrowser_tests/tests/nodeSearchBox.spec.tssrc/components/common/SearchFilterChip.test.tssrc/components/common/SearchFilterChip.vuesrc/components/searchbox/NodeSearchItem.vuesrc/components/sidebar/tabs/modelLibrary/DownloadItem.test.tssrc/components/sidebar/tabs/modelLibrary/DownloadItem.vue
| it('applies semantic badge class for input type', () => { | ||
| renderChip({ text: 'CLIP', badge: 'I', badgeClass: 'i-badge' }) | ||
| const badge = screen.getByText('I') | ||
| expect(badge.className).toContain('bg-green-500') | ||
| }) |
There was a problem hiding this comment.
Avoid asserting Tailwind utility classes in component tests.
These assertions couple tests to implementation styling (className) instead of user-visible behavior, which makes them brittle during visual refactors.
As per coding guidelines: "**/*.{test,spec}.ts: Do not write tests dependent on non-behavioral features like utility classes or styles."
Also applies to: 37-41, 52-60
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@src/components/common/SearchFilterChip.test.ts` around lines 31 - 35, The
test currently asserts Tailwind utility classes
(expect(badge.className).toContain('bg-green-500')) which is brittle; update the
tests that use renderChip (the "applies semantic badge class for input type"
test and the others flagged) to assert semantic behavior instead — e.g., check
the badge element exists, its text content/accessible name is 'I' and that it
has the semantic prop/class passed in (badgeClass like 'i-badge') or use
toHaveAttribute/toHaveClass with only non-utility class names, rather than
checking for Tailwind utility classes; locate the checks in the tests
referencing renderChip and replace utility-class assertions with these semantic
assertions.
| <div v-if="['cancelled', 'error'].includes(download.status ?? '')"> | ||
| <Chip | ||
| class="mt-2 h-6 bg-red-700 text-sm font-light" | ||
| <Tag | ||
| :label="t('electronFileDownload.cancelled')" | ||
| class="mt-2 bg-red-700 text-sm font-light" |
There was a problem hiding this comment.
Use a status-specific label for error state.
Line 6 includes error, but Line 8 always renders the cancelled label. That can mislead users when a download failed for a non-cancel reason.
💡 Proposed fix
- <Tag
- :label="t('electronFileDownload.cancelled')"
+ <Tag
+ :label="
+ t(
+ download.status === 'error'
+ ? 'electronFileDownload.error'
+ : 'electronFileDownload.cancelled'
+ )
+ "
class="mt-2 bg-red-700 text-sm font-light"
removable
`@remove`="handleRemoveDownload"
/>🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@src/components/sidebar/tabs/modelLibrary/DownloadItem.vue` around lines 6 -
9, The template currently treats both 'cancelled' and 'error' statuses the same
and always renders the cancelled label; update the conditional rendering around
the Tag (where download.status is checked) to use a status-specific label:
render t('electronFileDownload.cancelled') when download.status === 'cancelled'
and render t('electronFileDownload.error') (or the appropriate error translation
key) when download.status === 'error', keeping the same Tag component and
styling logic so users see the correct label for each status.
Summary
Chipwith customTagcomponent in all 3 remaining usagesSearchFilterChip: PrimeVue Chip+Badge → Tag (removable) + custom Badge (icon slot)NodeSearchItem: PrimeVue Chip → Tag (aliased asChipTagto avoid collision with PrimeVue Tag, migrated in follow-up PR)DownloadItem: PrimeVue Chip (removable) → Tag (removable).p-chip-remove-icontogetByRole('button', { name: 'Remove' })primevue/chipimports after this PRDepends on #10650 (Tag component).
Test plan
┆Issue is synchronized with this Notion page by Unito