Skip to content

feat: add Input/Output type sub-menu filters to Nodes panel sidebar#11294

Draft
comfydesigner wants to merge 2 commits intoComfy-Org:mainfrom
comfydesigner:nodes-panel-filters
Draft

feat: add Input/Output type sub-menu filters to Nodes panel sidebar#11294
comfydesigner wants to merge 2 commits intoComfy-Org:mainfrom
comfydesigner:nodes-panel-filters

Conversation

@comfydesigner
Copy link
Copy Markdown

@comfydesigner comfydesigner commented Apr 16, 2026

⚠️ Prototype / Reference Only — This PR is a working prototype for driving live demos, not production-ready code. It has not been through thorough testing or code review. Use as a reference for the intended UX/behavior.

Add Input Type and Output Type sub-menu filters to the existing filter dropdown in the Nodes panel sidebar.

Changes:

  • Add searchable sub-menus for Input Type and Output Type below existing category filters
  • Multi-select types with square checkboxes and colored socket dots
  • Selected types shown as stacked colored badges in parent menu
  • Footer with pluralized count and Clear all button
  • Filters applied to both search results and browse mode via NodeSearchService
  • Keep dropdown open on checkbox toggle
  • Fixed menu width to prevent layout shift

Files changed:

  • src/components/sidebar/tabs/NodeLibrarySidebarTabV2.vue
  • src/locales/en/main.json

- Add Input Type and Output Type sub-menus to the filter dropdown
- Each sub-menu has a searchable list of types with multi-select checkboxes
- Selected types shown as colored socket badges in the parent menu
- Footer shows selected count with Clear all button
- Type filters applied to both search and browse modes
- Keep dropdown open on checkbox toggle with @select.prevent
- Fix menu width stability with fixed w-48

Amp-Thread-ID: https://ampcode.com/threads/T-019d9399-6be0-76ab-aeb3-d5f688e5af43
Co-authored-by: Amp <amp@ampcode.com>
@vercel
Copy link
Copy Markdown

vercel bot commented Apr 16, 2026

Someone is attempting to deploy a commit to the ComfyUI Team on Vercel.

A member of the Team first needs to authorize it.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Apr 16, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 95114f0e-57f2-49f2-b08a-25ea5593c364

📥 Commits

Reviewing files that changed from the base of the PR and between 73d8c2f and 9228a84.

📒 Files selected for processing (2)
  • src/components/sidebar/tabs/NodeLibrarySidebarTabV2.vue
  • src/locales/en/main.json
✅ Files skipped from review due to trivial changes (1)
  • src/locales/en/main.json
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/components/sidebar/tabs/NodeLibrarySidebarTabV2.vue

📝 Walkthrough

Walkthrough

Added hierarchical Input and Output type submenu filters to the node library "all" filter UI with search, per-type selection, clear actions, and i18n keys; introduced reactive selected type state and integrated active type filters into node search and result post-filtering.

Changes

Cohort / File(s) Summary
Node Library Filter UI & Logic
src/components/sidebar/tabs/NodeLibrarySidebarTabV2.vue
Added hierarchical Input and Output type submenu filters with search, per-type checkboxes, visual selected indicators, and per-submenu "Clear all". Introduced reactive selectedInputTypes / selectedOutputTypes, search strings, computed availableInputTypes / availableOutputTypes, activeTypeFilters passed into searchNode, and an additional post-search predicate filter using filterDef.matches(node, value). Also adjusted checkbox rendering to conditionally show check icons and prevent default select events.
Internationalization
src/locales/en/main.json
Added g.typesSelected (pluralized) and g.clearTypeFilters i18n keys for selected-type counts and a "Clear type filters" label.

Sequence Diagram(s)

sequenceDiagram
  participant UI as NodeLibrarySidebarTabV2 (UI)
  participant Store as nodeDefStore
  participant Search as nodeSearchService
  participant Filter as filterDef
  UI->>Store: read available node type indexes
  UI->>UI: update selectedInputTypes / selectedOutputTypes
  UI->>Search: searchNode(query, activeTypeFilters)
  Search-->>UI: base search results
  UI->>Filter: apply filterDef.matches per activeTypeFilters
  Filter-->>UI: filtered activeNodes
  UI-->>UI: render nodes list based on activeNodes
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Poem

🐇 I hopped through lists of Input and Output, bright,
Checked types, cleared some, set selections light.
Search boxes scurry, matches tumble free—
Nodes line up neatly for a rabbit like me! 🥕✨

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately and specifically describes the main change: adding Input/Output type sub-menu filters to the Nodes panel sidebar.
Description check ✅ Passed The PR description is complete with summary, detailed changes list, and files changed, though it deviates from the template format by not using the specified section structure.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
End-To-End Regression Coverage For Fixes ✅ Passed PR title and commit subjects use feature language ('feat:') rather than bug-fix language, indicating this is a feature addition not requiring E2E regression test coverage.
Adr Compliance For Entity/Litegraph Changes ✅ Passed PR modifies only NodeLibrarySidebarTabV2.vue and main.json, neither under src/lib/litegraph/, src/ecs/, or graph entity files.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
⚔️ Resolve merge conflicts
  • Resolve merge conflict in branch nodes-panel-filters

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.

❤️ Share

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

Copy link
Copy Markdown
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 (1)
src/components/sidebar/tabs/NodeLibrarySidebarTabV2.vue (1)

44-44: ⚠️ Potential issue | 🟠 Major

Don’t keep type filters active after hiding the control.

The submenu only exists on the All tab, but activeNodes applies activeTypeFilters to Essentials and Blueprints too. After a tab switch, those tabs can stay filtered with no visible way to understand or clear the state.

💡 One safe fix
 const activeTypeFilters = computed<
   FuseFilterWithValue<ComfyNodeDefImpl, string>[]
 >(() => {
+  if (selectedTab.value !== 'all') {
+    return []
+  }
+
   const filters: FuseFilterWithValue<ComfyNodeDefImpl, string>[] = []
   const searchService = nodeDefStore.nodeSearchService
   // ...
 })

Also applies to: 529-540

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/components/sidebar/tabs/NodeLibrarySidebarTabV2.vue` at line 44, The
activeTypeFilters are being applied globally via activeNodes even when the
DropdownMenuRoot (submenu) is only shown for the All tab, causing hidden filters
to persist on Essentials/Blueprints; update the logic so filters only affect
nodes when selectedTab === 'all' (e.g. change the activeNodes computed getter or
filtering function to short-circuit and ignore/return unfiltered results when
selectedTab !== 'all'), or alternatively clear/reset activeTypeFilters when
selectedTab changes away from 'all' (add a watcher on selectedTab that sets
activeTypeFilters = [] when it becomes non-'all'); reference activeNodes,
activeTypeFilters, selectedTab and DropdownMenuRoot when making the change.
🤖 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/sidebar/tabs/NodeLibrarySidebarTabV2.vue`:
- Around line 145-158: The submenu search inputs in NodeLibrarySidebarTabV2.vue
(the <input> with v-model="inputTypeSearch" and the other input around lines
245-251) lack accessible names; add explicit accessible labeling by providing
either a visible <label for="..."> tied to a unique id or an
aria-label/aria-labelledby on each input (e.g.,
:aria-label="$t('nodeLibrary.searchTypes')" or similar localized string) so
screen readers and keyboard users can identify each field; ensure the id used in
the label matches the input id and use the same pattern for both the
inputTypeSearch field and the other submenu input.
- Around line 494-505: The activeTypeFilters computed currently emits one
FuseFilterWithValue per selected type, causing an unintended AND across the
submenu; change activeTypeFilters to emit at most one input-type filter and one
output-type filter by joining selectedInputTypes.value and
selectedOutputTypes.value into comma-separated strings and pushing a single {
filterDef: nodeDefStore.nodeSearchService.inputTypeFilter, value: joined } (and
similarly for outputTypeFilter) only when that submenu has selections, so
FuseFilter.matches() can use its built-in OR behavior; keep the same
FuseFilterWithValue type and ensure no filters are added when the selection
arrays are empty.

---

Outside diff comments:
In `@src/components/sidebar/tabs/NodeLibrarySidebarTabV2.vue`:
- Line 44: The activeTypeFilters are being applied globally via activeNodes even
when the DropdownMenuRoot (submenu) is only shown for the All tab, causing
hidden filters to persist on Essentials/Blueprints; update the logic so filters
only affect nodes when selectedTab === 'all' (e.g. change the activeNodes
computed getter or filtering function to short-circuit and ignore/return
unfiltered results when selectedTab !== 'all'), or alternatively clear/reset
activeTypeFilters when selectedTab changes away from 'all' (add a watcher on
selectedTab that sets activeTypeFilters = [] when it becomes non-'all');
reference activeNodes, activeTypeFilters, selectedTab and DropdownMenuRoot when
making the change.
🪄 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: 667e1bef-d093-446f-beb9-1f798d0a6da8

📥 Commits

Reviewing files that changed from the base of the PR and between a8e1fa8 and 73d8c2f.

📒 Files selected for processing (2)
  • src/components/sidebar/tabs/NodeLibrarySidebarTabV2.vue
  • src/locales/en/main.json

Comment on lines +145 to +158
<div class="px-3 pt-3 pb-1">
<div
class="flex items-center gap-2 rounded-md border border-border-default bg-comfy-input px-2 py-1"
>
<i
class="icon-[lucide--search] size-3.5 shrink-0 text-muted-foreground"
/>
<input
v-model="inputTypeSearch"
type="text"
:placeholder="$t('g.search') + '...'"
class="w-full border-0 bg-transparent text-sm outline-none placeholder:text-muted-foreground"
@keydown.stop
/>
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Label the submenu search fields.

Both new <input> controls rely on placeholder text only. That leaves them without a proper accessible name, which is a regression for keyboard/screen-reader navigation in the filter menu.

💡 Minimal fix
 <input
   v-model="inputTypeSearch"
   type="text"
+  :aria-label="$t('g.searchPlaceholder', { subject: $t('g.input') })"
   :placeholder="$t('g.search') + '...'"
   class="w-full border-0 bg-transparent text-sm outline-none placeholder:text-muted-foreground"
   `@keydown.stop`
 />
 <input
   v-model="outputTypeSearch"
   type="text"
+  :aria-label="$t('g.searchPlaceholder', { subject: $t('g.output') })"
   :placeholder="$t('g.search') + '...'"
   class="w-full border-0 bg-transparent text-sm outline-none placeholder:text-muted-foreground"
   `@keydown.stop`
 />

Also applies to: 245-251

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/components/sidebar/tabs/NodeLibrarySidebarTabV2.vue` around lines 145 -
158, The submenu search inputs in NodeLibrarySidebarTabV2.vue (the <input> with
v-model="inputTypeSearch" and the other input around lines 245-251) lack
accessible names; add explicit accessible labeling by providing either a visible
<label for="..."> tied to a unique id or an aria-label/aria-labelledby on each
input (e.g., :aria-label="$t('nodeLibrary.searchTypes')" or similar localized
string) so screen readers and keyboard users can identify each field; ensure the
id used in the label matches the input id and use the same pattern for both the
inputTypeSearch field and the other submenu input.

Comment on lines +494 to +505
const activeTypeFilters = computed<
FuseFilterWithValue<ComfyNodeDefImpl, string>[]
>(() => {
const filters: FuseFilterWithValue<ComfyNodeDefImpl, string>[] = []
const searchService = nodeDefStore.nodeSearchService
for (const type of selectedInputTypes.value) {
filters.push({ filterDef: searchService.inputTypeFilter, value: type })
}
for (const type of selectedOutputTypes.value) {
filters.push({ filterDef: searchService.outputTypeFilter, value: type })
}
return filters
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Group same-menu selections into one filter value.

Right now each checked type becomes its own filter entry, and activeNodes later applies every(...), so multi-select behaves like AND inside a submenu. For checkbox filters, users will expect OR within Input and within Output. FuseFilter.matches() already supports comma-separated OR values, so this should be collapsed here instead of emitting one filter per type.

💡 Minimal fix
 const activeTypeFilters = computed<
   FuseFilterWithValue<ComfyNodeDefImpl, string>[]
 >(() => {
   const filters: FuseFilterWithValue<ComfyNodeDefImpl, string>[] = []
   const searchService = nodeDefStore.nodeSearchService
-  for (const type of selectedInputTypes.value) {
-    filters.push({ filterDef: searchService.inputTypeFilter, value: type })
-  }
-  for (const type of selectedOutputTypes.value) {
-    filters.push({ filterDef: searchService.outputTypeFilter, value: type })
-  }
+  if (selectedInputTypes.value.size > 0) {
+    filters.push({
+      filterDef: searchService.inputTypeFilter,
+      value: Array.from(selectedInputTypes.value).join(',')
+    })
+  }
+  if (selectedOutputTypes.value.size > 0) {
+    filters.push({
+      filterDef: searchService.outputTypeFilter,
+      value: Array.from(selectedOutputTypes.value).join(',')
+    })
+  }
   return filters
 })
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/components/sidebar/tabs/NodeLibrarySidebarTabV2.vue` around lines 494 -
505, The activeTypeFilters computed currently emits one FuseFilterWithValue per
selected type, causing an unintended AND across the submenu; change
activeTypeFilters to emit at most one input-type filter and one output-type
filter by joining selectedInputTypes.value and selectedOutputTypes.value into
comma-separated strings and pushing a single { filterDef:
nodeDefStore.nodeSearchService.inputTypeFilter, value: joined } (and similarly
for outputTypeFilter) only when that submenu has selections, so
FuseFilter.matches() can use its built-in OR behavior; keep the same
FuseFilterWithValue type and ensure no filters are added when the selection
arrays are empty.

- Add 'Clear type filters' menu item below Output Type sub-menu
- Disabled state when no type filters active (data-[disabled] for Reka UI)
- Keep dropdown open on checkbox toggle for category filters
- Replace DropdownMenuItemIndicator with fixed-size spans to prevent layout shift
- Fix menu width to w-48 to prevent resize on check toggle

Amp-Thread-ID: https://ampcode.com/threads/T-019d9399-6be0-76ab-aeb3-d5f688e5af43
Co-authored-by: Amp <amp@ampcode.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant