diff --git a/docs/superpowers/specs/2026-05-23-node-local-interaction-design.md b/docs/superpowers/specs/2026-05-23-node-local-interaction-design.md new file mode 100644 index 00000000..fa3620b4 --- /dev/null +++ b/docs/superpowers/specs/2026-05-23-node-local-interaction-design.md @@ -0,0 +1,173 @@ +# Node-Local Interaction Design + +Date: 2026-05-23 +Status: Approved direction +Decision: Replace the fixed bottom composer as the primary node-editing surface with Minimax Hub-style node-local controls. + +## Goal + +Make the canvas feel like a direct visual workspace: the selected node is the center of editing, generation, and replacement. Controls should appear near the object they affect instead of living in a fixed bottom panel. + +This follows the Minimax Hub display principle from the reference: media remains visually dominant, common actions appear in a compact toolbar above the selected object, and deeper editing appears as a nearby contextual panel. + +## Current Problem + +The current `GenerationComposer` is mounted as a fixed bottom surface in `WorkflowCanvas`. It centralizes prompt, model, reference, and generation controls, but it also creates three interaction problems: + +1. It separates action from object. Users inspect a node on the canvas, move to the bottom to edit it, then look back at the canvas for feedback. +2. It competes with the graph. The bottom panel covers canvas space, edges, and nearby nodes even when the user is not editing that area. +3. It makes all node types feel like they share one global command surface, even though model choice, prompt, references, and output actions are scoped to a selected node. + +## Design Principles + +1. Object first: when a node is selected, its controls belong near that node. +2. Canvas first: media, graph structure, and edges stay visually dominant; controls are contextual and temporary. +3. Progressive disclosure: high-frequency actions are always close; detailed prompt and parameter editing opens only when needed. +4. No permanent bottom editor on desktop: the bottom of the viewport should not be occupied by a persistent composer. +5. Consistent control grammar: every generative node uses the same hierarchy of toolbar, inline editor, and model dialog. +6. Existing behavior remains: prompt editing, model selection, reference images, parameter edits, generate/replace flows, and shortcuts continue to work through the new surfaces. + +## Proposed Architecture + +### NodeContextToolbar + +`NodeContextToolbar` is a compact floating toolbar anchored above the selected node. + +Responsibilities: +- Show the active model or action name as the only text-heavy element. +- Expose high-frequency actions as icons with tooltips: select model, add reference, edit prompt, duplicate, delete, run, expand, and node-specific actions. +- Stay visually light and detached from the node content, matching the reference toolbar behavior. +- Hide when no single supported node is selected. + +Placement: +- Anchor to the selected node's screen bounds. +- Prefer top-center with 8-12 px gap. +- Reposition below or beside the node if the toolbar would leave the viewport. +- Track pan and zoom without causing layout shifts. + +### NodeInlineEditor + +`NodeInlineEditor` replaces the fixed bottom composer for selected-node editing. + +Responsibilities: +- Show prompt text, model controls, core generation parameters, reference thumbnails, and the primary generate/replace action. +- Open from toolbar edit actions, double-clicking editable node regions, or keyboard shortcuts. +- Follow the selected node rather than the viewport bottom. +- Use compact mode by default and expand only when the prompt or references need more space. + +Placement: +- Prefer below the selected node, aligned with the node's left edge. +- Use a max width and max height so it never becomes a full-screen bottom tray on desktop. +- Reposition above or to the side when there is insufficient space below. +- Keep a visible relationship to the selected node, even when collision handling moves it. + +### MultiSelectToolbar + +When multiple nodes are selected, show a multi-select toolbar instead of a single-node inline editor. + +Responsibilities: +- Group, align, duplicate, delete, run selected, and layout actions. +- Avoid prompt/model controls because there is no single active node context. + +### Empty Canvas Flow + +When no node is selected, the canvas should remain mostly empty. + +Creation entry points: +- Existing left-side tools. +- Connection quick-add menus. +- Canvas add action near the pointer or toolbar, if needed. + +The empty state should not reintroduce a permanent bottom composer. If a quick creation surface is needed, it should be a temporary popover tied to the user's click location. + +## Data Flow + +The new UI should reuse the existing composer behavior rather than reimplementing it. + +1. Selection state comes from the workflow store. +2. A shared interaction context derives the active mode: empty canvas, single supported node, unsupported node, multi-select, or process node. +3. Composer adapter logic is extracted from `GenerationComposer` into reusable helpers for reading drafts, building patches, and running generation. +4. `NodeInlineEditor` consumes the same draft helpers and writes changes back through existing node update actions. +5. Model selection continues to use the existing model search dialog and selected-model data structure. +6. Generation continues through existing run/generate actions; only the control surface changes. + +## Interaction Rules + +Single supported node: +- Select node: show `NodeContextToolbar`. +- Click edit or double-click editable area: open `NodeInlineEditor`. +- Press Escape: close editor first; keep node selected. Press Escape again to clear selection. +- Press Command+Enter while editing: run the selected node. + +Unsupported node: +- Show only safe generic actions such as duplicate, delete, comment, and expand. +- Do not show prompt/model editing controls. + +Generating node: +- Keep toolbar visible but disable destructive or conflicting actions. +- Show generation status near the node, not in a global bottom frame. + +Offscreen node: +- If the selected node scrolls out of view, hide the editor or show a small directional anchor. Do not leave a detached editor floating without context. + +## Visual Rules + +- Toolbar uses neutral surface, subtle border, compact icon buttons, and 8 px or smaller radius. +- Avoid large explanatory text inside the canvas UI. +- Prefer icons for actions and tooltips for clarification. +- The selected media/node remains the largest and clearest visual element. +- The editor should feel like an annotation attached to the node, not a separate app panel. +- No nested card styling: toolbar and editor are distinct floating surfaces. + +## Migration Plan + +Phase 1: Extract composer behavior. +- Move draft derivation, adapter logic, and build-patch helpers out of `GenerationComposer`. +- Add tests around the extracted helpers before changing UI behavior. + +Phase 2: Add contextual toolbar. +- Implement `NodeContextToolbar` anchored to selected node bounds. +- Wire model selection, edit, duplicate, delete, expand, and run actions. +- Keep the existing bottom composer during this phase as a fallback while toolbar behavior stabilizes. + +Phase 3: Add inline editor. +- Implement `NodeInlineEditor` using extracted composer helpers. +- Support image, video, audio, and prompt-capable nodes first. +- Add viewport collision handling and compact/expanded states. + +Phase 4: Remove bottom composer from primary flow. +- Stop rendering the fixed bottom composer in normal desktop canvas interaction. +- Preserve any business logic that was extracted. +- Replace empty-canvas creation with existing left toolbar and pointer-scoped quick-add behavior. + +Phase 5: Visual and regression pass. +- Verify toolbar/editor placement across zoom levels, pan positions, small windows, and dense graphs. +- Verify node generation flows, model switching, reference images, and keyboard shortcuts. + +## Testing Strategy + +Unit tests: +- Active interaction context derivation. +- Draft read/write helpers. +- Collision placement helpers. + +Component tests: +- Toolbar appears for a selected supported node. +- Toolbar hides for no selection. +- Multi-select toolbar replaces single-node editor. +- Inline editor writes prompt/model/parameter changes to the selected node. +- Escape and Command+Enter behave correctly. + +Browser/visual tests: +- Select image/video/audio nodes and confirm controls appear near the node. +- Pan and zoom while selected and confirm controls stay anchored. +- Confirm there is no fixed bottom composer in normal desktop interaction. +- Confirm dense graphs remain usable without the editor covering unrelated nodes unnecessarily. + +## Risks + +The largest risk is duplicating composer logic while moving the UI. That should be avoided by extracting the behavior first and letting new surfaces reuse it. + +The second risk is overlay placement complexity. This should be isolated in a small placement helper with tests and visual checks instead of scattering position math through node components. + +The third risk is removing a familiar global entry point too abruptly. During implementation, the toolbar and inline editor should ship behind a local feature flag until the full flow is verified.