Leveraging the fancy coverage functionality of #10930, this PR aims to
add coverage to missing dialogue models.
This has proven quite constructive as many of the dialogues have since
been shown to be bugged.
- The APINodes sign in dialog that displays when attempting to run a
workflow containing Partner nodes while not logged in was intended to
display a list of nodes required to execute the workflow. The import for
this component was forgotten in the original commit (#3532) and the
backing component was later knipped
- Error dialogs resulting are intended to display the file responsible
for the error, but the prop was accidentally left out during the
refactoring of #3265
- ~~The node library migration (#8548) failed to include the 'Edit
Blueprint' button, and had incorrect sizing and color on the 'Delete
Blueprint' button.~~
- On request, the library button changes were spun out to a separate PR
┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-11133-Add-missing-dialog-tests-33e6d73d3650812cb142d610461adcd4)
by [Unito](https://www.unito.io)
---------
Co-authored-by: GitHub Action <action@github.com>
The node library migration (#8548) failed to include the 'Edit
Blueprint' button, and had incorrect sizing and color on the 'Delete
Blueprint' button.
- Re-add edit blueprint which was missed in the migration
- Fix incorrect sizing on delete blueprint
- Fix color (lucide uses background, not text)
- Migrate all action buttons use our capital 'B' Button component and
use standardized variants where possible
Spun out of #11133
┆Issue is synchronized with this [Notion
page](https://app.notion.com/p/PR-11232-Fix-node-library-action-buttons-3426d73d365081339cafc7457c0b5421)
by [Unito](https://www.unito.io)
## Summary
Fix undersized delete and edit icons on user blueprint items in the node
library sidebar.
## Changes
- **What**: Changed blueprint action icons (trash, edit) from `size-3.5`
(14px) to `size-4` (16px), matching the standard icon size used across
the codebase.
## Review Focus
Trivial sizing fix — `size-4` is the codebase-wide convention for
iconify icons in buttons, and what the button base styles default SVGs
to.
┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-10992-fix-use-standard-size-4-for-blueprint-action-icons-33d6d73d365081be8c65f9e2a7b1d6ec)
by [Unito](https://www.unito.io)
## Summary
Add missing delete and bookmark actions for user blueprints in the V2
node library sidebar, fixing parity with the V1 sidebar.
## Changes
- **What**:
- Add delete button (inline + context menu) for user blueprints in
`TreeExplorerV2Node` and `TreeExplorerV2`
- Extract `isUserBlueprint()` helper in `subgraphStore` for DRY usage
across V1/V2 sidebars

## Review Focus
- `isUserBlueprint` consolidates logic previously duplicated between
`NodeTreeLeaf` and the new V2 components
- Context menu guard `contextMenuNode?.data` prevents showing empty
menus
- Folder `@contextmenu` handler clears stale `contextMenuNode` to
prevent wrong actions
┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-10827-fix-add-delete-bookmark-actions-for-blueprints-in-V2-node-library-sidebar-3366d73d36508111afd2c2c7d8ff0220)
by [Unito](https://www.unito.io)
## Summary
- Rename `text-xxxs`/`text-xxs` to `text-3xs`/`text-2xs` in design
system CSS — fixes `tailwind-merge` incorrectly classifying custom
font-size utilities as color classes, which clobbered text color
- Add `Badge` component with updated severity colors matching Figma
design (white text on colored backgrounds)
- Add Badge stories under `Components/Badges/Badge`
- Add unit tests including twMerge regression coverage
Split from #10438 per review feedback — this PR contains the
foundational Badge component; migration of consumers follows in a
separate PR.
## Test plan
- [x] Unit tests pass (`Badge.test.ts` — 12 tests)
- [x] Typecheck passes
- [x] Lint passes
- [ ] Verify Badge stories render correctly in Storybook
- [ ] Verify existing components using `text-2xs`/`text-3xs` render
unchanged
Fixes#10438 (partial)
┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-10580-refactor-add-Badge-component-and-fix-twMerge-font-size-detection-32f6d73d3650810dae7cd0d4af67fd1c)
by [Unito](https://www.unito.io)
## Summary
Rename `useFirebaseAuthStore` → `useAuthStore` and
`FirebaseAuthStoreError` → `AuthStoreError`. Introduce shared mock
factory (`authStoreMock.ts`) to replace 16 independent bespoke mocks.
## Changes
- **What**: Mechanical rename of store, composable, class, and store ID
(`firebaseAuth` → `auth`). Created
`src/stores/__tests__/authStoreMock.ts` — a shared mock factory with
reactive controls, used by all consuming test files. Migrated all 16
test files from ad-hoc mocks to the shared factory.
- **Files**: 62 files changed (rename propagation + new test infra)
## Review Focus
- Mock factory API design in `authStoreMock.ts` — covers all store
properties with reactive `controls` for per-test customization
- Self-test in `authStoreMock.test.ts` validates computed reactivity
Fixes#8219
## Stack
This is PR 1/5 in a stacked refactoring series:
1. **→ This PR**: Rename + shared test fixtures
2. #10484: Extract auth-routing from workspaceApi
3. #10485: Auth token priority tests
4. #10486: Decompose MembersPanelContent
5. #10487: Consolidate SubscriptionTier type
---------
Co-authored-by: Alexander Brown <drjkl@comfy.org>
## Summary
Migrate 13 component test files from @vue/test-utils to
@testing-library/vue as Phase 1 of incremental VTL adoption.
## Changes
- **What**: Rewrite 13 test files (88 tests) to use `render`/`screen`
queries, `userEvent` interactions, and `jest-dom` assertions. Add
`data-testid` attributes to 6 components for lint-clean icon/element
queries. Delete unused `src/utils/test-utils.ts`.
- **Dependencies**: `@testing-library/vue`,
`@testing-library/user-event`, `@testing-library/jest-dom` (installed in
Phase 0)
## Review Focus
- `data-testid` additions to component templates are minimal and
non-behavioral
- PrimeVue passthrough (`pt`) usage in UserAvatar.vue for icon testid
- 2 targeted `eslint-disable` in FormRadioGroup.test.ts where PrimeVue
places `aria-describedby` on wrapper div, not input
┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-10471-test-migrate-13-component-tests-from-VTU-to-VTL-Phase-1-32d6d73d36508159a33ffa285afb4c38)
by [Unito](https://www.unito.io)
---------
Co-authored-by: Amp <amp@ampcode.com>
## Summary
We've had some reports of issues selecting inputs/nodes when trying to
use the builder in LiteGraph mode and due to the complexity of the
canvas system, we're going to enable Nodes 2.0 when entering the builder
to ensure the best experience.
## Changes
- **What**:
- When entering builder select mode automatically switch to Nodes 2.0
- Extract reusable component from features toast
- Show popup telling user the mode was changed
- Add hidden setting for storing "don't show again" on the switch popup
## Review Focus
- I have not removed the LiteGraph selection code in case someone still
manages to enter the builder in LiteGraph mode, this should be cleaned
up in future
## Screenshots (if applicable)
<img width="423" height="224" alt="image"
src="https://github.com/user-attachments/assets/cc2591bc-e5dc-47ef-a3c6-91ca7b6066ff"
/>
┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-10337-feat-App-mode-Switch-to-Nodes-2-0-when-entering-builder-3296d73d3650818e9f3cdaac59d15609)
by [Unito](https://www.unito.io)
## Summary
Add a waveform-based audio player component (`WaveAudioPlayer`)
replacing the native `<audio>` element, with authenticated API fetch for
cloud audio playback.
## Changes
- **What**:
- Add `useWaveAudioPlayer` composable with waveform visualization from
audio data (Web Audio API `decodeAudioData`), playback controls, and
seek support
- Add `WaveAudioPlayer.vue` component with compact (inline waveform +
time) and expanded (full transport controls) variants
- Replace native `<audio>` in `MediaAudioTop.vue` and `ResultAudio.vue`
with `WaveAudioPlayer`
- Use `api.fetchApi()` instead of bare `fetch()` to include Firebase JWT
auth headers, fixing 401 errors in cloud environments
- Add Storybook stories and unit tests
## Review Focus
- The audio URL is fetched via `api.fetchApi()` with auth headers,
converted to a Blob URL, then passed to the native `<audio>` element.
This avoids 401 Unauthorized in cloud environments where `/api/view`
requires authentication.
- URL-to-route extraction logic (`url.includes(apiBase)`) handles both
full API URLs and relative paths.
[screen-capture.webm](https://github.com/user-attachments/assets/44e61812-0391-4b47-a199-92927e75f8b4)
┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-10158-feat-add-WaveAudioPlayer-with-waveform-visualization-and-authenticated-audio-fetch-3266d73d365081beab3fc6274c39fcd4)
by [Unito](https://www.unito.io)
---------
Co-authored-by: Amp <amp@ampcode.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-authored-by: Alexander Brown <drjkl@comfy.org>
## Summary
- Add keybinding preset system: save, load, switch, import, export, and
delete named keybinding sets stored via `/api/userdata/keybindings/`
- Preset selector dropdown with "Save Changes" button for modified
custom presets, and "Import keybinding preset" action
- More-options menu in header row with save as new, reset, delete,
import, and export actions
- Search box and menu teleported to settings dialog header (matching
templates modal layout)
- 11 unit tests for preset service CRUD operations
Fixes#1084Fixes#1085
## Test plan
- [ ] Open Settings > Keybinding, verify search box and "..." menu
appear in header
- [ ] Modify a keybinding, verify "Default *" shows modified indicator
- [ ] Use "Save as new preset" from menu, verify preset appears in
dropdown
- [ ] Switch between presets, verify unsaved changes prompt
- [ ] Export preset, import it back, verify bindings restored
- [ ] Delete a custom preset, verify reset to default
- [ ] Verify "Save Changes" button appears only on modified custom
presets
- [ ] Run `pnpm vitest run
src/platform/keybindings/presetService.test.ts`
┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-9681-feat-import-export-keybinding-presets-31e6d73d3650810f88e4d21b3df3e2dd)
by [Unito](https://www.unito.io)
---------
Co-authored-by: GitHub Action <action@github.com>
## Summary
Set topbar menus to non-modal so they dismiss when clicking
inputs/textareas inside nodes with Nodes 2.0 enabled.
## Changes
- **What**: Add `:modal="false"` to `ContextMenuRoot` in WorkflowTab and
`DropdownMenuRoot` in WorkflowActionsDropdown.

## Review Focus
Modal reka-ui menus set `body.pointer-events: none` and prevent
`focusOutside` dismissal. With Nodes 2.0, widget components use
`@pointerdown.capture.stop` to prevent node dragging, which also blocks
reka-ui's document-level outside-click detection. Non-modal menus allow
`focusin`-based dismissal, which is unaffected by pointerdown stopping.
## Testing
An E2E regression test for this fix requires Nodes 2.0 to be explicitly
enabled (feature-flag guarded), opening a specific topbar menu, and then
clicking inside a canvas node's textarea — an interaction sequence that
has no existing Playwright fixture/helper pattern in the codebase; the
fix itself is a one-line :modal="false" attribute change on reka-ui
primitives whose behavior is documented and tested upstream.
┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-10310-fix-set-topbar-menus-to-non-modal-so-they-dismiss-on-canvas-interaction-3286d73d3650815287d1c66c6ffd4814)
by [Unito](https://www.unito.io)
Co-authored-by: Amp <amp@ampcode.com>
## Summary
Fix high-resolution image preview expanding to full screen width, hiding
the close button.
## Changes
- **What**: Override scoped `ComfyImage` styles (`width/height: 100%`,
`object-fit: cover`) in the gallery context with `auto` sizing and
`max-width: 100vw; max-height: 100vh` constraints. The scoped
`[data-v-xxx]` attribute selector gave `comfy-image-main` higher
specificity than the existing `img.galleria-image` rule, so the new
selector `img.comfy-image-main.galleria-image` is used to win
specificity.
## Review Focus
- CSS specificity approach: using `.comfy-image-main.galleria-image` to
override Vue scoped styles without `!important`.
┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-10129-fix-high-res-image-preview-overflowing-screen-and-hiding-close-button-3266d73d36508191a03bcc75f9912421)
by [Unito](https://www.unito.io)
---------
Co-authored-by: Amp <amp@ampcode.com>
Co-authored-by: Alexander Brown <drjkl@comfy.org>
Co-authored-by: GitHub Action <action@github.com>
## Summary
Fix tree explorer nodes not filling the full width of the sidebar
container, causing text to overflow instead of truncating.
## Changes
- **What**: Add `min-w-0` to `TreeRoot` to allow flex shrinking within
sidebar. Add `w-full` and `min-w-0` to tree node rows so
absolutely-positioned virtualizer items fill the container width and
text truncates correctly.
<img width="365" height="749" alt="image"
src="https://github.com/user-attachments/assets/320910f3-52ad-4634-a935-6bd1a40aea7f"
/>
## Review Focus
The virtualizer renders each item with `position: absolute; left: 0` but
no explicit width, so rows would size to content rather than filling the
container. Adding `w-full` ensures rows stretch to 100% of the
virtualizer container, and `min-w-0` allows proper flex shrinking for
deep indentation levels.
┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-9964-fix-tree-explorer-nodes-not-filling-parent-container-width-3246d73d36508138be38fdcac15ae4ef)
by [Unito](https://www.unito.io)
Co-authored-by: Amp <amp@ampcode.com>
## Summary
Bake the frontend git commit hash into the build so it no longer needs
to be fetched from the server via `/api/system_stats`.
## Changes
- **What**: Add `__COMFYUI_FRONTEND_COMMIT__` build-time constant (via
Vite `define`) sourced from `git rev-parse HEAD` at build time. Falls
back to `"unknown"` if git is unavailable. `SystemStatsPanel` uses this
baked-in value for the "Frontend Version" row in cloud mode instead of
the server-provided `comfyui_frontend_version` field.
## Testing
Confirmed to display the actual commit.
<img width="1448" height="908" alt="Screenshot 2026-03-12 at 7 09 52 PM"
src="https://github.com/user-attachments/assets/2b42348a-5c3e-4509-aa84-1a259bba5f3f"
/>
## Review Focus
- The `getDisplayValue` override for `comfyui_frontend_version` —
cleanest way to swap the data source without restructuring the column
system.
- No cloud-side changes needed: the `sync-frontend-build` workflow
already checks out the frontend repo at the exact commit ref, so `git
rev-parse HEAD` returns the correct hash.
## Summary
Fix Vue warning about extraneous non-props attributes (`data-index`,
`style`) in `TreeExplorerV2Node`, which caused the Node Library sidebar
to freeze.
## Changes
- **What**: Added `defineOptions({ inheritAttrs: false })` and
`v-bind="$attrs"` on both node/folder `<div>` elements so the
virtualizer's positioning attributes are properly applied to the
rendered DOM.
## Review Focus
`TreeExplorerV2Node` has a fragment root (`<TreeItem as-child>` +
`<Teleport>`), so Vue cannot auto-inherit attrs. The virtualizer's
`style` (positioning) merges cleanly with `rowStyle` (`paddingLeft`
only).
┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-9735-fix-resolve-extraneous-attrs-warning-in-TreeExplorerV2Node-3206d73d3650817c8619e2145e98813d)
by [Unito](https://www.unito.io)
<img width="842" height="488" alt="스크린샷 2026-03-07 오후 9 39 20"
src="https://github.com/user-attachments/assets/9ac8bfcd-c882-4661-851f-b08838d4fed1"
/>
## Summary
- Add Storybook stories for WidgetInputText, WidgetTextarea, and
ScrubableNumberInput
- Reorganize story titles under `Components/Input/` to align with Figma
design system
- Fix PrimeIcons not rendering in Storybook (caused by
`[&_*]:!font-inter` override)
- Fix knip unused export warnings (dead code removal + workspace config)
## Test plan
- [ ] Run `pnpm storybook` and verify Components/Input/InputText stories
render
- [ ] Verify Components/Input/TextArea stories render with label and
copy button
- [ ] Verify Components/Input/Number stories render with -/+ icons
- [ ] Toggle Storybook theme between Light/Dark and confirm Number story
adapts
- [ ] Verify existing Button stories still render correctly
🤖 Generated with [Claude Code](https://claude.com/claude-code)
┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-9527-feat-add-text-widget-stories-and-Number-input-stories-31c6d73d3650817ba351cdef26a356c8)
by [Unito](https://www.unito.io)
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
- Buttons are marked as `touch-manipulation` so double-tapping on them
doesn't initiate a zoom.
- Move scrubable inputs to usePointerSwipe
- Strangely, swipe direction was inverted on mobile. This solves the
issue and simplifies code
- Moves event handlers into the scrubbable input component
- Make the slightly bigger buttons only apply when on mobile.
- Updates the workflows dropdown to have a check by the activeWorkflow
and truncate workflow names
- Displays dropzones (for the image preview) on mobile, but disables the
prompt to drag and drop an image if none is selected.
┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-9686-Mobile-input-tweaks-31f6d73d3650811d9025d0cd1ac58534)
by [Unito](https://www.unito.io)
## Summary
Replace legacy `SearchBox` (PrimeVue) and `SearchBoxV2` with the unified
`SearchInput` (reka-ui) component across all consumers.
## Changes
- **What**: Remove `SearchBox.vue`, `SearchBoxV2.vue`, their tests and
stories. Migrate all 14 consumers to `SearchInput`. Move layout classes
to `ComboboxRoot` for proper flex sizing. Extract filter button/chips in
`NodeLibrarySidebarTab`. Standardize modal search width to `flex-1
max-w-lg`.
- **Dependencies**: None new — `SearchInput` already existed using
reka-ui
## Review Focus
- `NodeLibrarySidebarTab.vue`: filter button and `SearchFilterChip`
rendering moved outside the search component
- `SearchInput.vue`: `className` now applied to `ComboboxRoot` instead
of `ComboboxAnchor` for correct flex layout
- Modal dialogs (`WorkflowTemplateSelectorDialog`, `AssetBrowserModal`,
`SampleModelSelector`) unified to `flex-1 max-w-lg`
┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-9644-feat-unify-search-components-by-replacing-SearchBox-SearchBoxV2-with-SearchInput-31e6d73d365081ebac55cb265f33b631)
by [Unito](https://www.unito.io)
---------
Co-authored-by: Amp <amp@ampcode.com>
Co-authored-by: github-actions <github-actions@github.com>
## Summary
Fix virtual scroll pagination not triggering in media asset panel list
view.
## Changes
**What**: `VirtualGrid` in `AssetsSidebarListView` was missing
`maxColumns=1` and had an incorrect default item height (200px vs actual
~48px). Without `maxColumns`, `cols` was calculated as
`floor(containerWidth / 200)` (e.g. 2), causing the row count to be
halved and `isNearEnd` to never fire correctly. Added `:max-columns="1"`
and `:default-item-height="48"` to fix pagination. Added regression
tests to `VirtualGrid.test.ts`.
## Review Focus
The root cause: `VirtualGrid.cols` computed as `floor(width/200)`
instead of `1` for single-column list layout, breaking spacer heights
and `approach-end` detection.
Test covers both the fix (approach-end fires with maxColumns=1) and the
bug reproduction (does not fire without it).
┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-9646-fix-virtual-scroll-pagination-not-working-in-media-asset-list-view-31e6d73d3650813d973ad19638ad6933)
by [Unito](https://www.unito.io)
## Summary
Additional fixes and updates based on testing
## Changes
- **What**:
- add warning to welcome screen & when sharing an app that has had all
outputs removed
- fix target workflow when changing mode via tab right click menu
- change build app text to be conditional "edit" vs "build" depending on
if an app is already defined
- update empty apps sidebar tab button text to make it clearer
- remove templates button from app mode (we will reintroduce this once
we have app templates)
- add "exit to graph" after applying default mode of node graph
- update cancel button to remove item from queue if it hasn't started
yet
- improve scoping of jobs/outputs to the current workflow [not perfect
but should be much improved]
- close sidebar tabs on entering app mode
- change tooltip to be under the workflow menu rather than covering the
button
┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-9511-feat-fix-App-mode-QA-feedback-2-31b6d73d365081d59bbbc13111100d46)
by [Unito](https://www.unito.io)
## Summary
Add SVG-based brand loading indicators (LogoCFillLoader,
LogoComfyWaveLoader) and use the wave loader as the app loading screen.
## Changes
- **What**: New `LogoCFillLoader` (bottom-to-top fill, plays once) and
`LogoComfyWaveLoader` (wave water-fill animation) components with
`size`, `color`, `bordered`, and `disableAnimation` props. Move all
loaders from `components/common/` to `components/loader/`. Use
`LogoComfyWaveLoader` in `App.vue` and `WorkspaceAuthGate.vue`. Render
loader above BlockUI overlay (z-1200) to prevent dim wash-out.
- **Dependencies**: None
## Review Focus
- SVG mask-based animation approach using `currentColor` for flexible
theming
- z-index layering: loader at z-1200 renders above PrimeVue BlockUI's
z-1100 modal overlay
- `disableAnimation` prop used in WorkspaceAuthGate to show static logo
outline during auth loading
## Screenshots (if applicable)
[loading_record.webm](https://github.com/user-attachments/assets/b34f7296-9904-4a42-9273-a7d5fda49d15)
Storybook stories added for both components under `Components/Loader/`.
┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-9433-feat-add-Logo-C-fill-and-Comfy-wave-loading-indicator-components-31a6d73d3650811cacfdcf867b1f835f)
by [Unito](https://www.unito.io)
---------
Co-authored-by: GitHub Action <action@github.com>
## Summary
Enable `better-tailwindcss/enforce-consistent-class-order` lint rule and
auto-fix all 1027 violations across 263 files. Stacked on #9427.
## Changes
- **What**: Sort Tailwind classes into consistent order via `eslint
--fix`
- Enable `enforce-consistent-class-order` as `'error'` in eslint config
- Purely cosmetic reordering — no behavioral or visual changes
## Review Focus
Mechanical auto-fix PR — all changes are class reordering only. This is
the largest diff but lowest risk since it changes no class names, only
their order.
**Stack:** #9417 → #9427 → **this PR**
Fixes#9300 (partial — 3 of 3 rules)
┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-9428-fix-enable-enforce-consistent-class-order-tailwind-lint-rule-31a6d73d3650811c9065f5178ba3e724)
by [Unito](https://www.unito.io)
## Summary
Enable `better-tailwindcss/enforce-canonical-classes` lint rule and
auto-fix all 611 violations across 173 files. Stacked on #9417.
## Changes
- **What**: Simplify Tailwind classes to canonical forms via `eslint
--fix`:
- `h-X w-X` → `size-X`
- `overflow-x-hidden overflow-y-hidden` → `overflow-hidden`
- and other canonical simplifications
- Enable `enforce-canonical-classes` as `'error'` in eslint config
## Review Focus
Mechanical auto-fix PR — all changes produced by `eslint --fix`. No
visual or behavioral changes; canonical forms are functionally
identical.
**Stack:** #9417 → **this PR** → PR 3 (class order)
Fixes#9300 (partial — 2 of 3 rules)
┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-9427-fix-enable-enforce-canonical-classes-tailwind-lint-rule-31a6d73d365081a49340d7d4640ede45)
by [Unito](https://www.unito.io)
## Summary
Add workflow sharing by URL and a multi-step ComfyHub publish wizard,
gated by feature flags and an optional profile gate.
## Changes
- **What**: Share dialog with URL generation and asset warnings;
ComfyHub publish wizard (Describe → Examples → Finish) with thumbnail
upload and tags; profile gate flow; shared workflow URL loader with
confirmation dialog
- **Dependencies**: None (new `sharing/` module under
`src/platform/workflow/`)
## Review Focus
- Three new feature flags: `workflow_sharing_enabled`,
`comfyhub_upload_enabled`, `comfyhub_profile_gate_enabled`
- Share service API contract and stale-share detection
(`workflowShareService.ts`)
- Publish wizard and profile gate state management
- Shared workflow URL loading and query-param preservation
┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-8951-feat-share-workflow-by-URL-30b6d73d3650813ebbfafdad775bfb33)
by [Unito](https://www.unito.io)
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: Amp <amp@ampcode.com>
Co-authored-by: github-actions <github-actions@github.com>
Co-authored-by: GitHub Action <action@github.com>
## Summary
Enable `better-tailwindcss/no-deprecated-classes` lint rule and auto-fix
all 103 violations across 65 files. First PR in a stacked series for
#9300.
## Changes
- **What**: Replace deprecated Tailwind v3 classes with v4 equivalents:
- `rounded` → `rounded-sm` (85)
- `flex-shrink-0` → `shrink-0` (16)
- `flex-grow` → `grow` (2)
- Enable `no-deprecated-classes` as `'error'` in eslint config
- Update one test asserting on `'rounded'` class string
## Review Focus
Mechanical auto-fix PR — all changes produced by `eslint --fix`. No
visual or behavioral changes (Tailwind v4 aliases these classes
identically).
Fixes#9300 (partial — 1 of 3 rules)
┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-9417-fix-enable-no-deprecated-classes-tailwind-lint-rule-31a6d73d3650819eaef4cf8ad84fb186)
by [Unito](https://www.unito.io)
Co-authored-by: Alexander Brown <drjkl@comfy.org>
## Summary
Replace hardcoded color and spacing values with semantic design tokens
and cache a computed variant class in StatusBadge.
## Changes
- **What**: Use Tailwind 4 CSS spacing variables in FormDropdownMenu
layout configs, replace zinc color utilities with semantic
`node-component-border` tokens in FormDropdownInput, wrap
`statusBadgeVariants()` in a `computed` for caching in StatusBadge.
## Review Focus
Straightforward token replacements and a computed caching change -- no
behavioral differences expected.
Fixes#9087Fixes#9086Fixes#7910
┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-9349-fix-replace-hardcoded-styles-with-design-tokens-and-cache-StatusBadge-variants-3186d73d36508185aae2e0753c9d1694)
by [Unito](https://www.unito.io)
## Summary
- In cloud mode, large generated images (4K, 8K+) cause browser freezing
when loaded at full resolution for preview display
- The cloud backend (ingest service) now supports a `res` query
parameter on `/api/view` that returns server-side resized JPEG (quality
80, max 512px) instead of redirecting to the full-size GCS original
- This PR adds `&res=512` to all image preview URLs in cloud mode,
reducing browser decode overhead from tens of MB to tens of KB
- Downloads still use the original resolution (no `res` param)
- No impact on localhost/desktop builds (`isCloud` compile-time
constant)
### without `?res`
302 -> png downloads
<img width="808" height="564" alt="스크린샷 2026-02-28 오후 6 53 03"
src="https://github.com/user-attachments/assets/7c1c62dd-0bc4-468d-9c74-7b98e892e126"
/>
<img width="323" height="137" alt="스크린샷 2026-02-28 오후 6 52 52"
src="https://github.com/user-attachments/assets/926aa0c4-856c-4057-96a0-d8fbd846762b"
/>
200 -> jpeg
### with `?res`
<img width="811" height="407" alt="스크린샷 2026-02-28 오후 6 51 55"
src="https://github.com/user-attachments/assets/d58d46ae-6749-4888-8bad-75344c4d868b"
/>
### Changes
- **New utility**: `getCloudResParam(filename?)` returns `&res=512` in
cloud mode for image files, empty string otherwise
- **Core stores**: `imagePreviewStore` appends `res` to node output
URLs; `queueStore.ResultItemImpl` gets a `previewUrl` getter (separates
preview from download URLs)
- **Applied to**: asset browser thumbnails, widget dropdown previews,
linear mode indicators, image compare node, background image upload
### Intentionally excluded
- Downloads (`getAssetUrl`) — need original resolution
- Mask editor — needs pixel-accurate data
- Audio/video/3D files — `res` only applies to raster images
- Execution-in-progress previews — use WebSocket blob URLs, not
`/api/view`
## Test plan
- [x] Unit tests for `getCloudResParam()` (5 tests: cloud/non-cloud,
image/non-image, undefined filename)
- [x] `pnpm typecheck` passes
- [x] `pnpm lint` passes
- [x] All 5332 unit tests pass
- [x] Manual verification on cloud.comfy.org: `res=512` returns 200 with
resized JPEG; without `res` returns 302 redirect to GCS PNG original
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
## Summary
Implement 11 Figma design discrepancies for the Node Library sidebar and
V2 Node Search dialog, aligning the UI with the [Toolbox Figma
design](https://www.figma.com/design/xMFxCziXJe6Denz4dpDGTq/Toolbox?node-id=2074-21394&m=dev).
## Changes
- **What**: Sidebar: reorder tabs (All/Essentials/Blueprints), rename
Custom→Blueprints, uppercase section headers, chevron-left of folder
icon, bookmark-on-hover for node rows, filter dropdown with checkbox
items, sort labels (Categorized/A-Z) with label-left/check-right layout,
hide section headers in A-Z mode. Search dialog: expand filter chips
from 3→6, add Recents and source categories to sidebar, remove "Filter
by" label. Pull foundation V2 components from merged PR #8548.
- **Dependencies**: Depends on #8987 (V2 Node Search) and #8548
(NodeLibrarySidebarTabV2)
## Review Focus
- Filter dropdown (`filterOptions`) is UI-scaffolded but not yet wired
to filtering logic (pending V2 integration)
- "Recents" category currently returns frequency-based results as
placeholder until a usage-tracking store is implemented
- Pre-existing type errors from V2 PR dependencies not in the base
commit (SearchBoxV2, usePerTabState, TextTicker, getProviderIcon,
getLinkTypeColor, SidebarContainerKey) are expected and will resolve
when rebased onto main after parent PRs land
┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-9085-feat-Node-Library-sidebar-and-V2-Search-dialog-Figma-design-improvements-30f6d73d36508175bf72d716f5904476)
by [Unito](https://www.unito.io)
---------
Co-authored-by: Yourz <crazilou@vip.qq.com>
Co-authored-by: github-actions <github-actions@github.com>
## Summary
Remove Tailwind `@apply` from Vue styles across `src/` and
`apps/desktop-ui/src/` to align with Tailwind v4 guidance, replacing
usages with template utilities or native CSS while preserving behavior.
## Changes
- **What**:
- Batch 1: migrated low-risk template/style utility bundles out of
`@apply`.
- Batch 2: converted PrimeVue/`:deep()` override `@apply` blocks to
native CSS declarations.
- Batch 3: converted `src/components/node/NodeHelpContent.vue` markdown
styling from `@apply` to native CSS/token-based declarations.
- Batch 4: converted final desktop pseudo-element `@apply` styles and
removed stale `@reference` directives no longer required.
- Verified `rg -n "^\s*@apply\b" src apps -g "*.vue"` has no real CSS
`@apply` directives remaining (only known template false-positive event
binding in `NodeSearchContent.vue`).
## Review Focus
- Visual parity in components that previously depended on `@apply` in
`:deep()` selectors and markdown content:
- topbar tabs/popovers, dialogs, breadcrumb, terminal overrides
- desktop install/dialog/update/maintenance surfaces
- node help markdown rendering
- Confirm no regressions from removal of now-unneeded `@reference`
directives.
## Screenshots (if applicable)
- No new screenshots included in this PR.
- Screenshot Playwright suite was run with `--grep="@screenshot"` and
reports baseline diffs in this environment (164 passed, 39 failed, 3
skipped) plus a teardown `EPERM` restore error on local path
`C:\Users\DrJKL\ComfyUI\LTXV\user`.
┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-9146-fix-eradicate-tailwind-apply-usage-in-vue-styles-3116d73d3650813d8642e0bada13df32)
by [Unito](https://www.unito.io)
---------
Co-authored-by: Amp <amp@ampcode.com>
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
## Summary
Redesign the missing models warning dialog to match the MissingNodes
dialog pattern with header/content/footer separation, type badges, file
sizes, and context-sensitive actions.
## Changes
- **What**: Split `MissingModelsWarning.vue` into `MissingModelsHeader`,
`MissingModelsContent`, `MissingModelsFooter` components following the
established MissingNodes pattern. Added model type badges (VAE,
DIFFUSION, LORA, etc.), inline file sizes, total download size, custom
model warnings, and context-sensitive footer buttons (Download all /
Download available / Ok, got it). Extracted security validation into
shared `missingModelsUtils.ts`. Removed orphaned `FileDownload`,
`ElectronFileDownload`, `useDownload`, and `useCivitaiModel` files.
- **Breaking**: None
## Review Focus
- Badge styling and icon button variants for theme compatibility
- Security validation logic preserved correctly in extracted utility
- E2e test locator updates for the new dialog structure
<img width="641" height="478" alt="스크린샷 2026-02-20 오후 7 35 23"
src="https://github.com/user-attachments/assets/ded27dc7-04e6-431d-9b2e-a96ba61043a4"
/>
┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-9014-refactor-Redesign-missing-models-dialog-30d6d73d365081809cb0c555c2c28034)
by [Unito](https://www.unito.io)
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: github-actions <github-actions@github.com>
## Summary
Virtualize the FormDropdownMenu to only render visible items, fixing
slow dropdown performance on cloud.
## Changes
- Integrate `VirtualGrid` into `FormDropdownMenu` for virtualized
rendering
- Add computed properties for grid configuration per layout mode
(grid/list/list-small)
- Extend `VirtualGrid` slot to provide original item index for O(1)
lookups
- Change container from `max-h-[640px]` to fixed `h-[640px]` for proper
virtualization
## Review Focus
- VirtualGrid integration within the popover context
- Layout mode switching with `:key="layoutMode"` to force re-render
- Grid style computed properties match original Tailwind classes
┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-8476-perf-virtualize-FormDropdownMenu-to-reduce-DOM-nodes-and-image-requests-2f86d73d365081b3a79dd5e0b84df944)
by [Unito](https://www.unito.io)
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **New Features**
* Dropdowns now render with a virtualized grid/list (stable indexes,
responsive sizing) and show an empty-state icon when no items exist.
* **Bug Fixes**
* Reduced layout shift and rendering glitches with improved
spacer/scroll calculations and more reliable media measurement.
* **Style**
* Simplified media rendering (standard img/video), unified item visuals
and hover/background behavior.
* **Tests**
* Added unit and end-to-end tests for virtualization, indexing, layouts,
dynamic updates, and empty states.
* **Breaking Changes**
* Dropdown item/selection shapes and related component props/events were
updated (adapter changes may be required).
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
---------
Co-authored-by: GitHub Action <action@github.com>