feat: move git graph legend to top-right corner to avoid overlap with graph
Deploy PR-Helper / deploy (push) Successful in 26s

This commit is contained in:
2026-06-21 14:43:16 +08:00
parent 1359c5c339
commit 9b26bcb1b8
+79
View File
@@ -129,6 +129,10 @@ const GitGraph = {
// Draw branch labels on the right side // Draw branch labels on the right side
this._drawBranchLabels(g, nodeMap, this._laneBranchMap, laneWidth, maxLane); this._drawBranchLabels(g, nodeMap, this._laneBranchMap, laneWidth, maxLane);
// Draw legend in top-right corner
const svgWidth = Math.max(width, graphWidth);
this._drawLegend(svg, this._laneBranchMap, svgWidth);
// Store for updates // Store for updates
this._nodeMap = nodeMap; this._nodeMap = nodeMap;
@@ -429,6 +433,81 @@ const GitGraph = {
}); });
}, },
// Draw legend in top-right corner of SVG
_drawLegend(svg, laneBranchMap, svgWidth) {
const legendPadding = 12;
const itemHeight = 20;
const circleRadius = 5;
const fontSize = 11;
// Collect unique branches
const branches = [];
const seen = new Set();
Object.values(laneBranchMap).forEach(info => {
if (!seen.has(info.name)) {
seen.add(info.name);
branches.push(info);
}
});
if (branches.length === 0) return;
// Create legend group
const legend = svg.append('g')
.attr('class', 'graph-legend');
// Calculate legend dimensions
const tempText = svg.append('text')
.attr('font-size', `${fontSize}px`)
.attr('font-family', 'system-ui, -apple-system, sans-serif');
let maxTextWidth = 0;
branches.forEach(b => {
tempText.text(b.name);
maxTextWidth = Math.max(maxTextWidth, tempText.node().getBBox().width);
});
tempText.remove();
const legendWidth = circleRadius * 2 + 8 + maxTextWidth + legendPadding * 2;
const legendHeight = branches.length * itemHeight + legendPadding * 2;
// Position in top-right
const legendX = svgWidth - legendWidth - 10;
const legendY = 10;
legend.attr('transform', `translate(${legendX},${legendY})`);
// Background
legend.append('rect')
.attr('width', legendWidth)
.attr('height', legendHeight)
.attr('rx', 6)
.attr('ry', 6)
.attr('fill', 'white')
.attr('stroke', '#e5e7eb')
.attr('stroke-width', 1)
.attr('opacity', 0.95);
// Legend items
branches.forEach((branch, i) => {
const itemY = legendPadding + i * itemHeight + itemHeight / 2;
legend.append('circle')
.attr('cx', legendPadding + circleRadius)
.attr('cy', itemY)
.attr('r', circleRadius)
.attr('fill', branch.color);
legend.append('text')
.attr('x', legendPadding + circleRadius * 2 + 8)
.attr('y', itemY + 4)
.text(branch.name)
.attr('font-size', `${fontSize}px`)
.attr('fill', '#374151')
.attr('font-family', 'system-ui, -apple-system, sans-serif');
});
},
_updateSelectionVisuals() { _updateSelectionVisuals() {
if (!this._nodes || !this._lanes) return; if (!this._nodes || !this._lanes) return;