24 KiB
PRD: Inspector Value Editing
Feature Name: Inspector Value Editing
Version: 1.0
Author: Æmotion Studio
Last Updated: January 15, 2026
Status: Draft
Executive Summary
This feature enables users to edit node widget values and text content directly from the Inspector Panel, eliminating the need to zoom into nodes or click through individual widgets on the canvas. When Sticky Info mode is active, users can click on any displayed value in the inspector to modify it inline, with changes immediately syncing to the corresponding node widget on the canvas.
Problem Statement
Currently, the Inspector Panel in ComfyUI-MagnifyGlass is read-only—users can view node parameters, copy text values, and navigate to nodes, but cannot modify values without leaving the inspector to interact with the actual node on the canvas. This creates friction in workflows where users need to:
- Frequently adjust parameters across multiple nodes
- Work with complex workflows where nodes are zoomed out or overlapping
- Edit prompt text in CLIPTextEncode nodes without hunting for the node
- Make quick iterative changes during experimentation
Goals & Success Metrics
Goals
- Enable inline editing of all widget types from the Inspector Panel
- Provide immediate visual feedback with live sync to canvas nodes
- Maintain constraint enforcement (min/max/step, valid dropdown options)
- Support editing in both the main Inspector Panel and Pop-Out Viewer
Success Metrics
- Users can edit any widget value without zooming to the node
- Edits are reflected on the canvas within 100ms of user interaction
- Zero invalid values can be committed (respecting widget constraints)
- Feature works seamlessly with Sticky Info mode
User Stories
-
As a user, I want to click on a seed value in the inspector and type a new number, so I can quickly iterate without finding the KSampler node.
-
As a user, I want to select a different sampler from a dropdown in the inspector, so I can compare samplers without navigating the canvas.
-
As a user, I want to edit my positive prompt text directly in the inspector, so I can refine prompts while keeping the overall workflow visible.
-
As a user, I want my edits in the Pop-Out Viewer to sync to the main canvas, so I can work on a second monitor.
-
As a user, I want the inspector to prevent invalid inputs (like negative steps), so I don't accidentally break my workflow.
Feature Specification
Scope: Widget Types Supported
All widget types that are normally editable in ComfyUI nodes:
| Widget Type | Inspector Editor | Example Widgets |
|---|---|---|
| text / string | Inline text input or expandable textarea | text (prompts), filename_prefix |
| number | Number input with step buttons | seed, steps, cfg, width, height |
| slider | Range slider with value display | denoise, strength |
| combo | Dropdown select | sampler_name, scheduler, ckpt_name |
| boolean | Toggle switch/checkbox | add_noise, return_with_leftover_noise |
| INT / FLOAT | Number input (like number) | Various numeric parameters |
Interaction Model
Entry Point
- No special "edit mode"—values are always editable when Sticky Info is active
- Click directly on a value to begin editing
- Sticky Info ensures the panel doesn't disappear during editing
Edit Behavior by Widget Type
┌─────────────────────────────────────────────────────────────────────┐
│ Widget Type │ Click Action │ Editor Component │
├─────────────────────────────────────────────────────────────────────┤
│ number/INT │ Select value │ <input type="number"> │
│ FLOAT │ Select value │ <input type="number" step> │
│ text (short) │ Inline edit │ <input type="text"> │
│ text (long) │ Expand textarea │ <textarea> with resize │
│ combo │ Show dropdown │ <select> or custom dropdown │
│ boolean │ Toggle immediately │ <input type="checkbox"> │
│ slider │ Show slider │ <input type="range"> + value │
└─────────────────────────────────────────────────────────────────────┘
Live Sync Behavior
- Changes sync immediately as the user types/selects (live sync)
- For text fields: sync on every keystroke (debounced ~50-100ms)
- For number inputs: sync on value change
- For combos/booleans: sync immediately on selection/toggle
Constraint Enforcement
- Numbers: Respect
min,max, andstepvalues from widget - Combos: Only show valid options from
widget.options - Text: No constraints (match node behavior)
- Booleans: Toggle between true/false only
UI/UX Design
Visual States
┌─────────────────────────────────────────────────────────────────────┐
│ STATE │ APPEARANCE │
├─────────────────────────────────────────────────────────────────────┤
│ Hover │ Value gets subtle highlight/underline │
│ Editing │ Value transforms into appropriate input control │
│ Syncing │ Brief loading indicator (optional) │
│ Error │ Red border on invalid input (prevented on commit) │
│ Success │ Value returns to display mode with new value │
└─────────────────────────────────────────────────────────────────────┘
Text Editing (Prompts)
For long text content (like prompts in CLIPTextEncode):
┌─────────────────────────────────────────────────────────────────────┐
│ Text │
│ ┌─────────────────────────────────────────────────────────────────┐ │
│ │ masterpiece, best quality, 1girl, solo, long hair, blonde... │ │
│ │ │ │
│ │ [Expandable textarea with drag-to-resize handle] │ │
│ └─────────────────────────────────────────────────────────────────┘ │
│ [Character count: 247] │
└─────────────────────────────────────────────────────────────────────┘
Number Editing (with constraints)
┌─────────────────────────────────────────────────────────────────────┐
│ steps │ ◀ │ 20 │ ▶ │ min: 1, max: 150, step: 1│
│ cfg │ ◀ │ 7.0 │ ▶ │ min: 0, max: 30, step: 0.5│
│ seed │ 1234567890 │ 🎲 (randomize button) │
└─────────────────────────────────────────────────────────────────────┘
Combo Editing (dropdowns)
┌─────────────────────────────────────────────────────────────────────┐
│ sampler_name │ euler_ancestral ▼ │
│ │ ┌─────────────────┐ │
│ │ │ euler │ │
│ │ │ euler_ancestral │ ← selected │
│ │ │ heun │ │
│ │ │ dpm_2 │ │
│ │ │ ... │ │
│ │ └─────────────────┘ │
└─────────────────────────────────────────────────────────────────────┘
Pop-Out Viewer Integration
The Pop-Out Viewer must support the same editing capabilities:
- All editable fields work identically to the main Inspector Panel
- Changes in Pop-Out sync to the main canvas immediately
- Communication via existing
popOutManager.sendInfo()mechanism, extended for edit commands
Technical Specification
Architecture Overview
┌─────────────────────────────────────────────────────────────────────┐
│ INSPECTOR PANEL │
│ ┌─────────────────────────────────────────────────────────────┐ │
│ │ UIManager.ts │ │
│ │ - renderSections() → Now renders editable fields │ │
│ │ - Creates WidgetEditor components per field │ │
│ └─────────────────────────────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌─────────────────────────────────────────────────────────────┐ │
│ │ WidgetEditorFactory.ts [NEW] │ │
│ │ - createEditor(widget, nodeId) → HTMLElement │ │
│ │ - Handles all widget types │ │
│ └─────────────────────────────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌─────────────────────────────────────────────────────────────┐ │
│ │ WidgetSyncManager.ts [NEW] │ │
│ │ - syncWidgetValue(nodeId, widgetName, value) │ │
│ │ - Finds node → widget → updates value │ │
│ │ - Triggers canvas redraw │ │
│ └─────────────────────────────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌─────────────────────────────────────────────────────────────┐ │
│ │ ComfyUI Canvas │ │
│ │ - Node widget value updated │ │
│ │ - Canvas redrawn automatically │ │
│ └─────────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────────┘
New Files to Create
1. src/info-panel/widget-editors/WidgetEditorFactory.ts
Factory class that creates the appropriate editor component for each widget type.
// Key exports
export interface WidgetEditorConfig {
nodeId: number;
widgetName: string;
widgetType: string;
currentValue: unknown;
options?: unknown; // Combo options array
min?: number; // Number constraints
max?: number;
step?: number;
onChange: (value: unknown) => void;
}
export class WidgetEditorFactory {
static createEditor(config: WidgetEditorConfig): HTMLElement;
}
2. src/info-panel/widget-editors/editors/ (individual editor components)
TextEditor.ts- Input/textarea for text widgetsNumberEditor.ts- Number input with stepper buttonsComboEditor.ts- Dropdown for combo widgetsBooleanEditor.ts- Toggle switch for booleansSliderEditor.ts- Range slider with value display
3. src/info-panel/WidgetSyncManager.ts
Handles synchronization between inspector edits and canvas nodes.
export class WidgetSyncManager {
/**
* Update a widget value on a node
* @returns true if successful, false if widget not found
*/
static syncWidgetValue(nodeId: number, widgetName: string, value: unknown): boolean;
/**
* Get widget constraints for validation
*/
static getWidgetConstraints(nodeId: number, widgetName: string): WidgetConstraints | null;
/**
* Force canvas redraw after widget update
*/
static triggerCanvasRedraw(): void;
}
Files to Modify
1. src/info-panel/UIManager.ts
Changes:
- Modify
renderSections()to detect editable fields - Integrate
WidgetEditorFactoryfor editable parameters - Add CSS classes for editable vs read-only states
- Handle focus management for inline editors
Key additions to renderSections():
// In section.content.map() for node parameters:
if (isEditableWidget(item)) {
return this.renderEditableField(item, nodeId);
} else {
return this.renderReadOnlyField(item);
}
2. src/info-panel/NodeDataExtractor.ts
Changes:
- Include widget metadata (min, max, step, options) in extracted parameters
- Add
isEditableflag to parameter items - Pass through
widgetNamefor sync operations
Modified ParameterItem interface:
export interface ParameterItem {
label: string;
value: string;
widgetName?: string; // Original widget name for syncing
widgetType?: string; // Widget type (number, combo, text, etc.)
isEditable?: boolean; // Whether this can be edited
constraints?: { // Widget constraints
min?: number;
max?: number;
step?: number;
options?: unknown[]; // For combo widgets
};
}
3. src/info-panel/InformationGatherer.ts
Changes:
- Pass widget constraints through to NodeInfo
- Include original widget reference for editing
4. src/types/comfyui.d.ts
Changes:
- Add
callbackproperty toComfyWidgetinterface (for triggering widget callbacks) - Add constraint types
5. css/info-panel.css (or equivalent)
Changes:
- Add styles for editable fields
- Hover/focus states for editors
- Textarea expansion animation
- Dropdown styling matching ComfyUI theme
Widget Value Sync Implementation
// WidgetSyncManager.ts core logic
static syncWidgetValue(nodeId: number, widgetName: string, value: unknown): boolean {
const app = (window as any).app;
const node = app.graph.getNodeById(nodeId);
if (!node || !node.widgets) return false;
const widget = node.widgets.find((w: any) => w.name === widgetName);
if (!widget) return false;
// Update widget value
widget.value = value;
// Trigger widget callback if it exists (some widgets need this)
if (typeof widget.callback === 'function') {
widget.callback(value, app.canvas, node, [0, 0], null);
}
// Mark node as dirty to trigger redraw
node.setDirtyCanvas(true, true);
// Force canvas redraw
app.canvas.setDirty(true, true);
return true;
}
Pop-Out Viewer Integration
Communication Protocol
Extend existing popOutManager to handle edit commands:
// In popout window → main window
interface PopOutEditCommand {
type: 'widget_edit';
nodeId: number;
widgetName: string;
value: unknown;
}
// Main window receives and applies edit
window.addEventListener('message', (event) => {
if (event.data.type === 'widget_edit') {
WidgetSyncManager.syncWidgetValue(
event.data.nodeId,
event.data.widgetName,
event.data.value
);
}
});
Edge Cases & Error Handling
| Scenario | Handling |
|---|---|
| Node deleted while editing | Detect node absence, show toast, close editor |
| Widget removed by custom node logic | Validate widget exists before sync |
| Invalid number (out of bounds) | Clamp to min/max, show feedback |
| Empty required text field | Allow (match node behavior) |
| Combo option no longer valid | Fallback to first option or current |
| Pop-out window closed during edit | Edits in main window still work |
| Rapid successive edits | Debounce sync calls (50-100ms) |
Implementation Phases
Phase 1: Core Infrastructure
- Create
WidgetSyncManagerwith basic sync logic - Create
WidgetEditorFactoryskeleton - Modify
NodeDataExtractorto include widget metadata - Add basic CSS for editable fields
Phase 2: Editor Components
- Implement
NumberEditor(most common) - Implement
TextEditor(short text + expandable) - Implement
ComboEditor(dropdowns) - Implement
BooleanEditor(toggle) - Implement
SliderEditor
Phase 3: UIManager Integration
- Modify
renderSections()for editable rendering - Add focus management
- Handle escape to cancel / enter to confirm
Phase 4: Pop-Out Viewer
- Extend
popOutManagermessage protocol - Mirror editor components in popout HTML
- Test cross-window sync
Phase 5: Polish & Testing
- Theme compatibility (all ComfyUI themes)
- Keyboard navigation (tab between fields)
- Performance optimization (large workflows)
- Accessibility (ARIA labels)
File Structure After Implementation
src/info-panel/
├── widget-editors/
│ ├── WidgetEditorFactory.ts [NEW]
│ ├── WidgetSyncManager.ts [NEW]
│ ├── editors/
│ │ ├── BaseEditor.ts [NEW]
│ │ ├── TextEditor.ts [NEW]
│ │ ├── NumberEditor.ts [NEW]
│ │ ├── ComboEditor.ts [NEW]
│ │ ├── BooleanEditor.ts [NEW]
│ │ └── SliderEditor.ts [NEW]
│ └── index.ts [NEW]
├── CanvasHighlighter.ts
├── EventManager.ts
├── InfoPanel.ts
├── InformationGatherer.ts [MODIFIED]
├── NodeDataExtractor.ts [MODIFIED]
├── NodeSelector.ts
├── PositionManager.ts
├── StateManager.ts
├── UIManager.ts [MODIFIED]
├── ValueFormatter.ts
└── index.ts
Testing Strategy
Unit Tests
WidgetSyncManager.syncWidgetValue()correctly updates nodesWidgetEditorFactorycreates correct editor types- Constraint validation works for all widget types
Integration Tests
- Edit a number → verify node widget value changed
- Edit a combo → verify dropdown selection applied
- Edit text → verify prompt updated in CLIPTextEncode
- Pop-out edit → verify main canvas receives update
Manual Testing Checklist
- KSampler: Edit seed, steps, cfg, sampler, scheduler
- CLIPTextEncode: Edit positive/negative prompts
- CheckpointLoader: Change model via dropdown
- LoadImage: Verify read-only fields stay read-only
- Test with Sticky Info enabled and disabled
- Test in Pop-Out Viewer
- Test theme compatibility (Dark, Light, Nord, etc.)
Risks & Mitigations
| Risk | Likelihood | Impact | Mitigation |
|---|---|---|---|
| Widget callbacks break | Medium | High | Wrap callback in try/catch, fallback to direct value set |
| Custom node widgets unsupported | High | Medium | Gracefully fallback to read-only for unknown types |
| Performance with many editable fields | Low | Medium | Lazy-load editors, virtualize long lists |
| Theme CSS conflicts | Medium | Low | Use scoped class names, CSS variables |
Dependencies
- No external dependencies required
- Uses existing ComfyUI APIs (
app.graph,node.widgets) - Uses existing project infrastructure (TypeScript, Vite build)
Future Enhancements (Out of Scope for v1.0)
- Undo/Redo integration with ComfyUI history
- Batch editing (change same param across multiple nodes)
- Favorites/pinned parameters
- Node title editing from inspector
- Parameter presets/snapshots
- Keyboard shortcuts for common actions (randomize seed, etc.)
Appendix A: Existing Codebase Reference
Key Files for Handoff
| File | Purpose | Relevance |
|---|---|---|
| UIManager.ts | Renders inspector UI, handles sections | Main integration point |
| NodeDataExtractor.ts | Extracts widget data from nodes | Needs widget metadata additions |
| InformationGatherer.ts | Gathers node/widget info under cursor | Widget constraints source |
| comfyui.d.ts | Type definitions | Extend for editing APIs |
| StateManager.ts | Panel state management | Sticky Info detection |
ComfyUI Widget Structure
// Typical widget object from node.widgets
{
name: "steps",
type: "number",
value: 20,
options: {
min: 1,
max: 10000,
step: 1,
precision: 0
},
callback: (v, canvas, node, pos, event) => { ... }
}
Sticky Info Setting
// Check if Sticky Info is enabled
const isSticky = stateManager.state.settings["🔍MagnifyGlass.InfoPanelPersist"];
Appendix B: Changelog Template
## v1.11.0 (TBD)
**🎛️ Inspector Value Editing**
* **Direct Editing**: Click any parameter value in the Inspector Panel to edit it inline.
* **Supported Types**: Numbers, text, dropdowns, toggles, and sliders—all editable without zooming.
* **Live Sync**: Changes apply instantly to nodes on the canvas.
* **Pop-Out Support**: Edit values from the detached viewer window.
* **Smart Constraints**: Respects min/max/step values and dropdown options from each widget.
End of PRD