Here’s a complete stand-alone sample that I think demonstrates what you want.
I didn’t bother with the rounded rectangles – just about the overlapping margins.
Basically I think you need to account for all four possible combinations of selected items to determine the top margin.
<!DOCTYPE html>
<html>
<head>
<title>Overlapping Items</title>
<!-- Copyright 1998-2024 by Northwoods Software Corporation. -->
</head>
<body>
<div id="myDiagramDiv" style="border: solid 1px black; width:100%; height:600px"></div>
<textarea id="mySavedModel" style="width:100%;height:250px"></textarea>
<script src="https://unpkg.com/gojs"></script>
<script id="code">
const myDiagram =
new go.Diagram("myDiagramDiv",
{
initialScale: 3,
"undoManager.isEnabled": true,
"ModelChanged": e => { // just for demonstration purposes,
if (e.isTransactionFinished) { // show the model data in the page's TextArea
document.getElementById("mySavedModel").textContent = e.model.toJson();
}
}
});
const NORMAL = 1;
const SELECTED = 3;
myDiagram.nodeTemplate =
new go.Node("Vertical", {
selectionAdorned: false
})
.add(
new go.TextBlock()
.bind("text"),
new go.Panel("Vertical", {
itemTemplate:
new go.Panel("Auto", {
stretch: go.GraphObject.Horizontal,
click: (e, pan) => {
e.diagram.model.commit(m => {
m.set(pan.data, "selected", !pan.data.selected);
});
}
})
.bind(new go.Binding("margin", "itemIndex", i => new go.Margin(i > 0 ? -NORMAL : 0, 0, 0, 0)).ofObject())
.bind("margin", "selected", (s, pan) => updateMargins(pan))
.add(
new go.Shape({ fill: "white" })
.bind("stroke", "selected", s => s ? "dodgerblue" : "black")
.bind("strokeWidth", "selected", s => s ? SELECTED : NORMAL),
new go.TextBlock({ margin: new go.Margin(4, 4, 3, 4) })
.bind("text")
)
})
.bind("itemArray", "items")
);
function updateMargins(pan) {
const idx = pan.itemIndex;
const container = pan.panel;
const next = (idx+1 <= container.elements.count-1) ? container.elt(idx+1) : null;
if (next) next.margin = marg(pan.data.selected, next.data.selected);
const prev = (idx > 0) ? container.elt(idx-1) : null;
if (prev) return marg(prev.data.selected, pan.data.selected);
return new go.Margin(0);
}
function marg(a, b) {
if (a && b) return new go.Margin(-SELECTED, 0, 0, 0);
if (a && !b) return new go.Margin(0);
if (!a && b) return new go.Margin(0);
return new go.Margin(-NORMAL, 0, 0, 0);
}
myDiagram.model = new go.GraphLinksModel(
[
{ key: 1, text: "Alpha", items:
[
{ text: "first" },
{ text: "second" },
{ text: "third" },
{ text: "fourth" },
]
},
]);
</script>
</body>
</html>