SESSION 12.16 HIERARCHY CONNECTOR WIRED
Documentation for Sessions
Session 12.16 - Hierarchy Connector Mode Wired to Canvas
Overview
Completed the Hierarchy Connector Mode by wiring the visual UI to the canvas click behavior. When active, clicking a container now assigns it as the parent of the currently selected widget, instead of just selecting the container.
What Was Implemented
1. Canvas Input/Output Bindings ✅
File: libs/libs-ui/editor-ui/src/lib/components/editor-ui/editor-ui.component.html
Added two new bindings to the canvas:
<lib-editor-canvas
...
[hierarchyConnectorModeInput]="hierarchyConnectorMode()"
...
(containerClickedForConnection)="onContainerClickedForConnection($event)"
></lib-editor-canvas>
2. Canvas Component Changes ✅
File: libs/libs-widgets/widgets/src/lib/widgets/editor-canvas/editor-canvas.component.ts
A. Added Input for Hierarchy Connector Mode
@Input() set hierarchyConnectorModeInput(value: boolean) {
this.hierarchyConnectorMode.set(value);
}
B. Added Output Event
@Output() containerClickedForConnection = new EventEmitter<string>(); // Emits container ID
C. Added Signal for Mode State
// 🔗 Hierarchy Connector Mode
readonly hierarchyConnectorMode = signal(false);
D. Modified Widget Selection Logic
onSelectWidget(widget: Widget): void {
// 🔗 If hierarchy connector mode is active and widget is a container, connect instead of select
if (this.hierarchyConnectorMode() && widget.type === 'container') {
console.log('[Canvas] 🔗 Hierarchy Connector Mode - Container clicked:', widget.name, widget.id);
this.containerClickedForConnection.emit(widget.id);
return; // Don't select, just connect
}
this.selectionService.selectWidget(widget, this.widgetAction);
}
E. Added Canvas Class for Visual Feedback
readonly canvasClasses = computed(() => ({
...
// 🔗 Hierarchy Connector Mode
'hierarchy-connector-mode': this.hierarchyConnectorMode(),
...
}));
3. Visual Feedback Styles ✅
File: libs/libs-widgets/widgets/src/lib/widgets/editor-canvas/editor-canvas.component.scss
Added comprehensive styles for visual feedback when in connector mode:
// 🔗 Hierarchy Connector Mode Styles
.editor-canvas.hierarchy-connector-mode {
cursor: crosshair !important;
// Highlight all container widgets for connection
::ng-deep lib-container-widget {
position: relative;
&::before {
content: '';
position: absolute;
top: -2px;
left: -2px;
right: -2px;
bottom: -2px;
border: 3px dashed #10b981;
border-radius: 8px;
background: rgba(16, 185, 129, 0.05);
pointer-events: none;
z-index: 1000;
animation: connector-pulse 2s infinite;
}
&::after {
content: '🔗 Click to Connect';
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
background: #10b981;
color: white;
padding: 8px 16px;
border-radius: 8px;
font-size: 14px;
font-weight: 600;
pointer-events: none;
z-index: 1001;
box-shadow: 0 4px 12px rgba(16, 185, 129, 0.4);
animation: connector-bounce 1s infinite;
}
&:hover::before {
border-color: #059669;
background: rgba(5, 150, 105, 0.1);
animation: connector-pulse-fast 1s infinite;
}
&:hover::after {
background: #059669;
transform: translate(-50%, -50%) scale(1.05);
}
}
}
Visual Effects:
- ✅ Cursor changes to crosshair across entire canvas
- ✅ All containers get a pulsing green dashed border
- ✅ "🔗 Click to Connect" label appears centered in each container
- ✅ Hover effect intensifies the pulse and changes colors
- ✅ Animations make the mode feel alive and interactive
4. Editor UI Event Handler ✅
File: libs/libs-ui/editor-ui/src/lib/components/editor-ui/editor-ui.component.ts
Added handler for when a container is clicked in connector mode:
/**
* 🔗 Handle container clicked for connection in hierarchy connector mode
*/
onContainerClickedForConnection(containerId: string): void {
const selectedWidget = this.selectedWidgets()[0];
if (!selectedWidget) {
console.warn('[EditorUI] No widget selected for connection');
return;
}
console.log('[EditorUI] 🔗 Connecting widget to container:', {
widgetId: selectedWidget.id,
widgetName: selectedWidget.name,
containerId,
});
// Re-parent the selected widget to the clicked container
this.handleWidgetReparent(selectedWidget.id, containerId);
// Deactivate hierarchy connector mode
this.hierarchyConnectorMode.set(false);
console.log('[EditorUI] ✅ Connection complete - Hierarchy Connector Mode DEACTIVATED');
// TODO: Show toast notification
}
Logic Flow:
- Get the currently selected widget
- If no widget selected, warn and return
- Call
handleWidgetReparent()to update parent/child relationships - Auto-deactivate the connector mode
- Log success
How It Works (Complete Flow)
User Journey
- User selects a widget (e.g., Text Widget) on the canvas
- Opens Properties Panel → Hierarchy section
- Clicks "Visual Connect" button
- Button turns green with pulsing animation
hierarchyConnectorModesignal set totrue- Signal propagates to canvas via
[hierarchyConnectorModeInput]
- Canvas applies visual feedback
- Cursor changes to crosshair
- All containers get green pulsing border + "🔗 Click to Connect" label
- User clicks on a container
- Canvas
onSelectWidget()detects the mode is active - Instead of selecting, emits
containerClickedForConnectionevent with container ID
- Canvas
- Editor UI handles the connection
- Receives container ID via
onContainerClickedForConnection() - Calls
handleWidgetReparent()to update widget'sparentId - Updates parent/child arrays
- Emits
widgetsChangeevent
- Receives container ID via
- Mode auto-deactivates
hierarchyConnectorModeset back tofalse- Visual feedback removed
- Button returns to normal blue gradient
- Widget is now nested
- Widget disappears from canvas top-level (filtered by
topLevelWidgets()) - Widget appears inside container (via
childWidgets) - Widget Tree updates to show correct hierarchy
- Widget disappears from canvas top-level (filtered by
Testing Instructions
Test 1: Hierarchy Connector Mode (NEW!)
- Refresh browser (Ctrl+Shift+R / Cmd+Shift+R)
- Create a Text Widget and a Container Widget on canvas
- Select the Text Widget
- Open Properties Panel → scroll to Hierarchy section
- Click "Visual Connect" button
- Expected visual changes:
- Button turns green with pulsing animation ✅
- Text changes to "Click container to connect..." ✅
- Cursor becomes crosshair across canvas ✅
- Container widget gets:
- Green pulsing dashed border ✅
- "🔗 Click to Connect" label in center ✅
- Click on the Container Widget
- Expected results:
- Text Widget disappears from canvas top-level ✅
- Text Widget appears inside container ✅
- Widget Tree updates to show Text Widget nested under Container ✅
- Connector mode auto-deactivates (button returns to blue) ✅
- Console shows success logs ✅
Test 2: Mode Cancellation
- Activate connector mode (click "Visual Connect")
- Instead of clicking a container, click the button again
- Expected: Mode deactivates, visual feedback removed
Test 3: No Widget Selected
- Deselect all widgets (click on canvas background)
- Try to activate connector mode
- Expected: Button should be disabled (no widget to connect)
Console Logs to Watch For
When everything works correctly, you should see:
[PropertiesPanel] 🔗 Hierarchy Connector Mode: ACTIVATED
[EditorUI] 🔗 Hierarchy Connector Mode: ACTIVATED
[Canvas] 🔗 Hierarchy Connector Mode - Container clicked: Container Widget <container-id>
[EditorUI] 🔗 Connecting widget to container: { widgetId: ..., widgetName: ..., containerId: ... }
[EditorUI] 🏗️ Re-parenting widget <widget-id> to <container-id>
[Canvas] 🎯 Top-level widgets: 1 / 2
[WidgetTree] 🌲 Top-level widgets for tree: 1 / 2
[EditorUI] ✅ Connection complete - Hierarchy Connector Mode DEACTIVATED
Known Issues & Next Steps
✅ DONE
- Hierarchy Connector Mode UI
- Wire mode to canvas
- Visual feedback (cursor, borders, labels, animations)
- Auto-deactivate after connection
- Console logging for debugging
⏳ TODO
- Add toast notification on successful connection
- Fix drag-and-drop from palette → container (still investigating)
- Implement drag-based re-parenting for existing widgets
- Add keyboard shortcut to activate connector mode (e.g., Ctrl+Shift+C)
- Add option to connect to "Canvas" (remove parent) via special click zone
Drag-and-Drop Status
The user reported that drag-and-drop from palette → container is still not working. Initial investigation shows:
- ✅ Canvas correctly detects drops on containers and defers to
DropZoneDirective - ✅ Container has
libDropZonedirective applied - ✅
dropZoneEnabled()is true - ✅
onDropped()handler is defined and has extensive logging - ✅
DropZoneDirectivereads multiple drag data formats
Possible causes:
- Z-index issue: Container might be behind other elements
- Event propagation: Some event handler might be stopping propagation
- Data format mismatch: Palette might be setting drag data in a format the container doesn't recognize
- Pointer events: Container might have
pointer-events: nonein some cases
Next debugging step: Add console logs to see if the container's DropZoneDirective is even firing when dragging from palette.
Files Modified
Core Functionality
- ✅
libs/libs-widgets/widgets/src/lib/widgets/editor-canvas/editor-canvas.component.ts- Input, output, signal, selection logic, classes - ✅
libs/libs-widgets/widgets/src/lib/widgets/editor-canvas/editor-canvas.component.scss- Visual feedback styles - ✅
libs/libs-ui/editor-ui/src/lib/components/editor-ui/editor-ui.component.ts- Event handler - ✅
libs/libs-ui/editor-ui/src/lib/components/editor-ui/editor-ui.component.html- Canvas bindings
Documentation
- ✅
sessions/sessionID.json- Updated to 12.16 - ✅
docs/english/sessions/session-12/SESSION-12.16-HIERARCHY-CONNECTOR-WIRED.md- This file
Key Architectural Decisions
Why Not Select the Container?
When in connector mode, clicking a container should NOT select it because:
- The user's intent is to connect the currently selected widget, not to select a new widget
- Selecting would change the Properties Panel, losing the connection context
- It provides clear, predictable behavior: one action, one outcome
Why Auto-Deactivate?
The mode auto-deactivates after connection because:
- Most users will only want to connect once
- It prevents accidental connections
- The visual feedback (crosshair, borders) is intense and should be temporary
- Users can easily re-activate if needed
Why Use ::ng-deep?
The visual feedback uses ::ng-deep to pierce Angular's view encapsulation because:
- Container widgets are separate components with their own encapsulation
- The feedback needs to be applied from the canvas level
- It's the most reliable way to ensure all containers get the effect
- Alternative would be to add a class directly to containers, which is more complex
User Feedback Integration
"it did not work. When we click on the container, it selects it, instead of activating the inheritance."
Status: ✅ FIXED - Container clicks now trigger connection instead of selection
"This is why I said the active mode has to be smart, intuitive, and modify the behavior of the normal clicks/ui/ux."
Status: ✅ IMPLEMENTED - Mode changes cursor, adds visual feedback, and modifies click behavior
"And do not forget to FIX the drag and drop inside the container, that's still broken - maybe just be some silly z-index or not recognizing where a new container is."
Status: ⏳ INVESTIGATING - Need to add more diagnostic logs to identify the issue
Session Progress
Session 12.16 - Wired Hierarchy Connector Mode to canvas, implemented visual feedback, and enabled click-to-connect functionality.
Next Session 12.17 - Debug and fix drag-and-drop from palette → container.