Browse Source

fix node properties positioning

main
Stephanie Gredell 5 months ago
parent
commit
8937943c7b
  1. 68
      static/app.js
  2. 10
      static/style.css

68
static/app.js

@ -232,12 +232,21 @@ export class CanvasApp {
} }
}); });
this.canvas.addEventListener('click', () => { this.canvas.addEventListener('click', (e) => {
// If this is part of a double-click sequence (detail > 1), ignore it
if (e.detail > 1) {
return;
}
if (this.connectionStart) { if (this.connectionStart) {
this.connectionStart.group.classList.remove('selected'); this.connectionStart.group.classList.remove('selected');
this.connectionStart = null; this.connectionStart = null;
} }
this.hidePropsPanel();
// Don't hide props panel if clicking on it
if (!this.nodePropsPanel.contains(e.target)) {
this.hidePropsPanel();
}
this.clearSelection(); this.clearSelection();
}); });
@ -275,6 +284,11 @@ export class CanvasApp {
this.hidePropsPanel(); this.hidePropsPanel();
}); });
// Prevent props panel from closing when clicking inside it
this.nodePropsPanel.addEventListener('click', (e) => {
e.stopPropagation();
});
document.addEventListener('keydown', (e) => { document.addEventListener('keydown', (e) => {
if (e.key === 'Backspace' || e.key === 'Delete') { if (e.key === 'Backspace' || e.key === 'Delete') {
if (this.selectedConnection) { if (this.selectedConnection) {
@ -312,12 +326,35 @@ export class CanvasApp {
return; return;
} }
const bbox = node.group.getBBox(); // Get the node's actual screen position using getBoundingClientRect
const ctm = node.group.getCTM(); const nodeRect = node.group.getBoundingClientRect();
const screenX = ctm.e + bbox.x; const containerRect = this.canvasContainer.getBoundingClientRect();
const screenY = ctm.f + bbox.y + bbox.height; const panelWidth = 220; // From CSS: #node-props-panel width
panel.style.left = (screenX + this.canvasContainer.getBoundingClientRect().left) + 'px'; const panelHeight = 400; // Estimated height for boundary checking
panel.style.top = (screenY + this.canvasContainer.getBoundingClientRect().top) + 'px';
// Try to position dialog to the right of the node
let dialogX = nodeRect.right + 10;
let dialogY = nodeRect.top;
// Check if dialog would go off the right edge of the screen
if (dialogX + panelWidth > window.innerWidth) {
// Position to the left of the node instead
dialogX = nodeRect.left - panelWidth - 10;
}
// Check if dialog would go off the bottom of the screen
if (dialogY + panelHeight > window.innerHeight) {
// Move up to keep it visible
dialogY = window.innerHeight - panelHeight - 10;
}
// Ensure dialog doesn't go above the top of the screen
if (dialogY < 10) {
dialogY = 10;
}
panel.style.left = dialogX + 'px';
panel.style.top = dialogY + 'px';
// Hide all groups first // Hide all groups first
const allGroups = panel.querySelectorAll('.prop-group, #label-group, #compute-group, #lb-group'); const allGroups = panel.querySelectorAll('.prop-group, #label-group, #compute-group, #lb-group');
@ -343,10 +380,22 @@ export class CanvasApp {
this.propsSaveBtn.disabled = false; this.propsSaveBtn.disabled = false;
panel.style.display = 'block'; panel.style.display = 'block';
// Trigger smooth animation
setTimeout(() => {
panel.classList.add('visible');
}, 10);
} }
hidePropsPanel() { hidePropsPanel() {
this.nodePropsPanel.style.display = 'none'; const panel = this.nodePropsPanel;
panel.classList.remove('visible');
// Hide after animation completes
setTimeout(() => {
panel.style.display = 'none';
}, 200);
this.propsSaveBtn.disabled = true; this.propsSaveBtn.disabled = true;
this.activeNode = null; this.activeNode = null;
} }
@ -368,7 +417,6 @@ export class CanvasApp {
if (this.selectedNode) { if (this.selectedNode) {
this.selectedNode.deselect(); this.selectedNode.deselect();
this.selectedNode = null; this.selectedNode = null;
this.hidePropsPanel();
} }
} }

10
static/style.css

@ -275,7 +275,7 @@ body {
} }
#node-props-panel { #node-props-panel {
position: absolute; position: fixed;
width: 220px; width: 220px;
background-color: var(--color-bg-sidebar); background-color: var(--color-bg-sidebar);
border: 1px solid var(--color-border); border: 1px solid var(--color-border);
@ -285,6 +285,14 @@ body {
box-shadow: 0 0 10px rgba(0, 0, 0, 0.6); box-shadow: 0 0 10px rgba(0, 0, 0, 0.6);
display: none; display: none;
z-index: 10; z-index: 10;
opacity: 0;
transform: scale(0.95);
transition: opacity 0.2s ease-out, transform 0.2s ease-out;
&.visible {
opacity: 1;
transform: scale(1);
}
h3 { h3 {
margin-top: 0; margin-top: 0;

Loading…
Cancel
Save