Skip to content

feat(nodes-2): advanced-inputs affordance overhaul (stacked on #12678)#12725

Draft
comfydesigner wants to merge 3 commits into
Comfy-Org:mainfrom
comfydesigner:advanced-params-affordance
Draft

feat(nodes-2): advanced-inputs affordance overhaul (stacked on #12678)#12725
comfydesigner wants to merge 3 commits into
Comfy-Org:mainfrom
comfydesigner:advanced-params-affordance

Conversation

@comfydesigner

Copy link
Copy Markdown
Contributor

Stacked on #12678 (`node-compaction`). Target is `main` because `node-compaction` isn't on the upstream repo — the PR diff currently includes the node-compaction commits. Once #12678 merges, the diff will collapse to just the new advanced-inputs commits.

Summary

Make the advanced-inputs controls discoverable and consistent. The global setting was buried 3 clicks deep, and we were calling the same concept "advanced parameters" in one place and "advanced inputs" in another. This PR aligns the naming and (in follow-up commits) restructures the per-node footer affordance into a popover that surfaces the global option contextually.

Changes

  • What (so far): Renamed the user-facing "Show advanced parameters" / its tooltip → "Show advanced inputs" / matching tooltip in the global settings panel. English locale only.
  • What (planned, not yet committed):
    • `NodeFooter.vue` Case 4 — replace the single-button advanced footer with a popover containing a tri-radio: "Show on this node only" / "Show on all nodes" (sets global) / "Hide on all nodes" (clears global).
    • `LGraphNode.vue` — hide the per-node footer affordance when the global `Comfy.Node.AlwaysShowAdvancedWidgets` setting is on.
    • Add new i18n keys for the popover options.
  • Breaking: None expected.

Review Focus

  • Naming choice: "advanced inputs" over "advanced parameters" — all internal symbols already use "inputs". Open to feedback.
  • Workflow sharing semantics (deferred): Per-node `showAdvanced` is serialized into workflow JSON. If author A has `Comfy.Node.AlwaysShowAdvancedWidgets: true` and shares a workflow, recipient B with the setting off will see whatever the per-node state says. Simplest defensible position: "global is a viewer preference (doesn't travel); per-node override travels and wins." Will file as a follow-up Linear issue.

Screenshots

(pending)

Alex added 3 commits June 5, 2026 20:55
- Drop body font from text-sm to text-xs; header chevron and pin to 16px
- Header padding 8/12/8 → 4 all sides (height 40 → 24 px)
- Header text color matches widget labels (text-node-component-slot-text)
- Footer height 36 → 44 px (visible 16 → 24 px); single 12 px corner radius
- Footer subgraph/advanced text uses grey token; error stays white
- Widget row 28 → 24 px; stepper buttons 32 → 24 px square
- Slot dot 12 → 8 px; socket row 24 → 20 px; slot row padding 24 → 8 px
- Label column 80 px, label↔input gap 8 px
- Select trigger p-0 + pl-7 to align values with number widget x-position
- Drop-shadow on the node root for combined body+footer silhouette
- Softer header surface tokens for default themes
- Drop unused body-border overlay element
The previous pl-7 (28 px) was designed to align dropdown values with
number input values across a widget row — number values start at
x = 28 px from the widget left (24 px stepper button + 4 px padding),
so dropdowns padded to the same x position read as a vertical column
in mixed-widget nodes like KSampler.

For nodes that have no number widgets (e.g. Video Stitch, with only
a dropdown and a toggle), the 28 px padding looked like wasted space:
no values to align with, just a visible empty column on the left of
every dropdown.

The proper fix would be context-aware padding: the parent node
detects whether any sibling widget is a stepper-input, and propagates
that down. Tracked separately. For now, revert to the visually
consistent 8 px (gap-2 rhythm used elsewhere on the node — header
content gap, widget label↔input gap, etc.). This trades the cross-row
column alignment in mixed-widget nodes for a cleaner standalone
appearance.
The global settings panel called this 'Show advanced parameters' while
the per-node footer button calls it 'Show advanced inputs'. Same
underlying state (widget.options.advanced), different label, no good
reason — pick one and use it consistently.

Going with 'advanced inputs' because:

- All internal symbols already agree: showAdvancedInputsButton,
  hideAdvancedInputsButton, showAdvanced state on the litegraph node,
  Comfy.Node.AlwaysShowAdvancedWidgets setting key.
- 'Inputs' is unambiguous (parameter could mean input or output).
- Renaming one i18n string is safer than renaming code.

Touches only the English locale. Other locales already differed and
will need their own pass; not in scope here.
@coderabbitai

coderabbitai Bot commented Jun 9, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

This PR is a comprehensive design system refinement that updates color tokens for light/dark themes, refactors node component styling to use smaller rounded corners, adjusts spacing and sizing across slots and widgets, replaces PrimeIcons with Lucide icons, and updates related test assertions.

Changes

Design System and Component Styling Update

Layer / File(s) Summary
Design system color tokens
packages/design-system/src/css/style.css
--node-component-header-surface CSS custom property updated from --color-smoke-400 to --color-smoke-200 in :root, and from --color-charcoal-800 to --color-charcoal-700 in .dark-theme.
Core node component structure and theme-aware styling
src/renderer/extensions/vueNodes/components/LGraphNode.vue
Adds useColorPaletteStore import and isLightTheme computed state for theme detection. Template wrapper switches from text-sm to text-xs and applies conditional drop-shadow based on theme. Removes separate root-border overlay and simplifies node-inner-wrapper class composition. Increases resize-handle stroke-width. Refactors all rounding computables (bodyRoundingClass, shapeClass, selectionShapeClass, bypassOverlayClass, mutedOverlayClass) from larger 2xl radii to smaller xl variants.
Node header and footer styling with rounding refactor
src/renderer/extensions/vueNodes/components/NodeHeader.vue, src/renderer/extensions/vueNodes/components/NodeFooter.vue, src/renderer/extensions/vueNodes/components/NodeFooter.test.ts
NodeHeader adjusts template class list (tighter padding/density), reduces icon sizes (chevron-down, pinned indicator), and updates headerShapeClass rounding with new rounded-*-xl/rounded-*-2xl combinations. NodeFooter refactors bottom-radius computation with new getBottomRadius(nodeShape, corners) function, increases tab height from h-9 to h-11, adjusts padding from pb-4 to pb-3 across all button variants, adds text-node-component-slot-text to full-width buttons. NodeFooter.test updates assertions from pixel-based radii (e.g., rounded-br-[20px]) to rounded-*-xl classes.
Slot component sizing and spacing adjustments
src/renderer/extensions/vueNodes/components/InputSlot.vue, src/renderer/extensions/vueNodes/components/OutputSlot.vue, src/renderer/extensions/vueNodes/components/SlotConnectionDot.vue
InputSlot reduces right padding from pr-6 to pr-2. OutputSlot reduces height from h-6 to h-5 and left padding from pl-6 to pl-2. SlotConnectionDot reduces dot dimensions: multi branch from h-6 w-3 to h-5 w-2, and single branch from size-3 to size-2.
Number input and select widget styling
src/components/common/ScrubableNumberInput.vue, src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.vue, src/renderer/extensions/vueNodes/widgets/components/WidgetSelectDefault.vue
ScrubableNumberInput updates container class bindings, sets size="unset" on buttons, replaces pi pi-minus/pi pi-plus icons with lucide--minus/lucide--plus (size-4), and changes input overlay style from text-sm to text-xs. WidgetInputNumberInput reduces wrapper height from h-7 to h-6 and corner rounding from rounded-lg to rounded-md. WidgetSelectDefault adjusts trigger button sizing, label typography/padding, and removes chevron translate-x styling.
Widget layout base styling and spacing
src/renderer/extensions/vueNodes/widgets/components/WidgetWithControl.vue, src/renderer/extensions/vueNodes/widgets/components/layout/WidgetLayoutField.vue, src/renderer/extensions/vueNodes/widgets/components/layout/index.ts
WidgetWithControl adds mr-1 class to ValueControlButton. WidgetLayoutField updates grid gap from gap-1 to gap-2 and border radius from rounded-lg to rounded-md. WidgetInputBaseClass exported constant changes rounding from 'rounded-lg' to 'rounded-md'.
English locale string updates
src/locales/en/main.json
g.enterSubgraph capitalization changes from "Enter Subgraph" to "Enter subgraph". rightSidePanel.globalSettings.showAdvanced and showAdvancedTooltip terminology changes from "advanced parameters" to "advanced inputs".

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

  • Comfy-Org/ComfyUI_frontend#12455: Both PRs touch WidgetInputBaseClass in src/renderer/extensions/vueNodes/widgets/components/layout/index.ts (main changes its base rounding from rounded-lgrounded-md, retrieved adds a [[readonly]]:bg-component-node-widget-background-disabled styling), so the changes intersect at the same exported class list.

Suggested labels

size:L

Suggested reviewers

  • christian-byrne
  • dante01yoon

Poem

A rabbit hops through corners round,
From xl to 2xl all around,
With tighter padding, sleeker sight,
Icons dancing—lucide's light! ✨
The design system glows just right! 🎨

🚥 Pre-merge checks | ✅ 7
✅ Passed checks (7 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the main objective: restructuring the advanced inputs controls and aligning naming conventions for improved discoverability.
Description check ✅ Passed The description provides a comprehensive summary with clear sections covering objectives, current changes, and planned work. It addresses the template structure adequately.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
End-To-End Regression Coverage For Fixes ✅ Passed PR uses "feat" and "style" prefixes, not bug-fix language. Regression test coverage is only required for fixes, not feature/style changes.
Adr Compliance For Entity/Litegraph Changes ✅ Passed PR modifies only presentation-layer Vue components and styling; no changes to core graph entity files in src/lib/litegraph/ or src/ecs/, so ADR 0003/0008 compliance check is not applicable.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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.

@github-actions

github-actions Bot commented Jun 9, 2026

Copy link
Copy Markdown

🎨 Storybook: loading Building...

@github-actions

github-actions Bot commented Jun 9, 2026

Copy link
Copy Markdown

🎭 Playwright: ⏳ Running...

@coderabbitai coderabbitai Bot left a comment

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.

Actionable comments posted: 1

🧹 Nitpick comments (1)
src/renderer/extensions/vueNodes/components/NodeFooter.test.ts (1)

201-209: ⚡ Quick win

Add a left-tab radius assertion in dual-tab mode

This case only checks enter-tab rounding. Add an assertion for the error tab so
the dual-tab seam/corner regression is caught in tests.

As per coding guidelines, "Write tests for all changes, especially bug fixes to catch future regressions."

Example assertion add-on
 it('enter tab uses right-only rounding in dual-tab mode (Case 1)', () => {
   renderFooter({
     isSubgraph: true,
     hasAnyError: true,
     showErrorsTabEnabled: true
   })
+  const errorBtn = screen.getByText('Error').closest('button')
   const enterBtn = screen.getByTestId('subgraph-enter-button')
+  expect(errorBtn?.className ?? '').not.toMatch(/rounded-br-xl/)
   expect(enterBtn.className).toMatch(/rounded-br-xl/)
 })
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/renderer/extensions/vueNodes/components/NodeFooter.test.ts` around lines
201 - 209, The test currently only asserts the right-side rounding for the enter
tab; add an assertion that the error tab has the left-side radius in dual-tab
mode by calling screen.getByTestId for the error tab (e.g.,
'subgraph-error-button' or the existing error tab test id used elsewhere) after
renderFooter(...) and assert its className matches the left-only rounding regex
(e.g., /rounded-bl-xl/) so the dual-tab seam/corner regression is covered.

Source: Coding guidelines

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/renderer/extensions/vueNodes/components/NodeFooter.vue`:
- Around line 257-271: The computed errorRadiusClass uses getBottomRadius(shape)
which lacks a left-side option and can incorrectly round the inner seam; update
getBottomRadius to accept a 'left' corners option (extend the type to 'both' |
'right' | 'left') and return 'rounded-bl-xl' when corners === 'left' (respecting
the existing RenderShape.BOX and CARD logic), then set errorRadiusClass =
computed(() => getBottomRadius(shape, 'left')) so the error button rounds the
outer left corner correctly.

---

Nitpick comments:
In `@src/renderer/extensions/vueNodes/components/NodeFooter.test.ts`:
- Around line 201-209: The test currently only asserts the right-side rounding
for the enter tab; add an assertion that the error tab has the left-side radius
in dual-tab mode by calling screen.getByTestId for the error tab (e.g.,
'subgraph-error-button' or the existing error tab test id used elsewhere) after
renderFooter(...) and assert its className matches the left-only rounding regex
(e.g., /rounded-bl-xl/) so the dual-tab seam/corner regression is covered.
🪄 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: 8ca33e84-88f7-4080-b3cb-98aa1fa8226a

📥 Commits

Reviewing files that changed from the base of the PR and between b93338c and 54b4b89.

📒 Files selected for processing (15)
  • packages/design-system/src/css/style.css
  • src/components/common/ScrubableNumberInput.vue
  • src/locales/en/main.json
  • src/renderer/extensions/vueNodes/components/InputSlot.vue
  • src/renderer/extensions/vueNodes/components/LGraphNode.vue
  • src/renderer/extensions/vueNodes/components/NodeFooter.test.ts
  • src/renderer/extensions/vueNodes/components/NodeFooter.vue
  • src/renderer/extensions/vueNodes/components/NodeHeader.vue
  • src/renderer/extensions/vueNodes/components/OutputSlot.vue
  • src/renderer/extensions/vueNodes/components/SlotConnectionDot.vue
  • src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.vue
  • src/renderer/extensions/vueNodes/widgets/components/WidgetSelectDefault.vue
  • src/renderer/extensions/vueNodes/widgets/components/WidgetWithControl.vue
  • src/renderer/extensions/vueNodes/widgets/components/layout/WidgetLayoutField.vue
  • src/renderer/extensions/vueNodes/widgets/components/layout/index.ts

Comment on lines 257 to +271
function getBottomRadius(
nodeShape: RenderShape | undefined,
size: '17px' | '20px',
corners: 'both' | 'right' = 'both'
): string {
if (nodeShape === RenderShape.BOX) return ''
const prefix =
nodeShape === RenderShape.CARD || corners === 'right'
? 'rounded-br'
: 'rounded-b'
const key =
`${prefix}-${size === '17px' ? '17' : '20'}` as keyof typeof RADIUS_CLASS
return RADIUS_CLASS[key]
return nodeShape === RenderShape.CARD || corners === 'right'
? 'rounded-br-xl'
: 'rounded-b-xl'
}

const footerRadiusClass = computed(() =>
getBottomRadius(shape, hasAnyError ? '20px' : '17px')
)
const footerRadiusClass = computed(() => getBottomRadius(shape))

const errorRadiusClass = computed(() => getBottomRadius(shape, '20px'))
const errorRadiusClass = computed(() => getBottomRadius(shape))

const enterRadiusClass = computed(() => getBottomRadius(shape, '20px', 'right'))
const enterRadiusClass = computed(() => getBottomRadius(shape, 'right'))

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 | 🟡 Minor | ⚡ Quick win

Fix corner selection for dual-tab error button

At Line 269, errorRadiusClass uses getBottomRadius(shape) which can
apply right-side rounding to the left tab in dual-tab layouts. That rounds the
inner seam instead of the outer edge.

Proposed fix
-function getBottomRadius(
-  nodeShape: RenderShape | undefined,
-  corners: 'both' | 'right' = 'both'
-): string {
+function getBottomRadius(
+  nodeShape: RenderShape | undefined,
+  corners: 'both' | 'left' | 'right' = 'both'
+): string {
   if (nodeShape === RenderShape.BOX) return ''
-  return nodeShape === RenderShape.CARD || corners === 'right'
-    ? 'rounded-br-xl'
-    : 'rounded-b-xl'
+  if (nodeShape === RenderShape.CARD) {
+    return corners === 'right' || corners === 'both' ? 'rounded-br-xl' : ''
+  }
+  if (corners === 'left') return 'rounded-bl-xl'
+  if (corners === 'right') return 'rounded-br-xl'
+  return 'rounded-b-xl'
 }
 
 const footerRadiusClass = computed(() => getBottomRadius(shape))
-const errorRadiusClass = computed(() => getBottomRadius(shape))
+const errorRadiusClass = computed(() => getBottomRadius(shape, 'left'))
 const enterRadiusClass = computed(() => getBottomRadius(shape, 'right'))
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/renderer/extensions/vueNodes/components/NodeFooter.vue` around lines 257
- 271, The computed errorRadiusClass uses getBottomRadius(shape) which lacks a
left-side option and can incorrectly round the inner seam; update
getBottomRadius to accept a 'left' corners option (extend the type to 'both' |
'right' | 'left') and return 'rounded-bl-xl' when corners === 'left' (respecting
the existing RenderShape.BOX and CARD logic), then set errorRadiusClass =
computed(() => getBottomRadius(shape, 'left')) so the error button rounds the
outer left corner correctly.

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