diff --git a/src/flowchart-generator.html b/src/flowchart-generator.html
index 1d06087..7684cba 100644
--- a/src/flowchart-generator.html
+++ b/src/flowchart-generator.html
@@ -185,6 +185,77 @@
.flowchart-edge {
stroke: #1f2328 !important;
}
+ /* v4.13.0 — visual polish. Adds a visible selection ring (was
+ previously only the .selected class without a distinct colour),
+ a hover tint, an enlarged resize-handle hit area, a smoother
+ modal dialog animation, and a proper opaque background behind
+ edge labels so they stay readable across curved connectors. */
+ .flowchart-node {
+ cursor: grab;
+ transition: filter 0.12s ease-out;
+ }
+ .flowchart-node:hover .flowchart-node-shape {
+ filter: drop-shadow(0 0 2px rgba(37, 99, 235, 0.45));
+ }
+ .flowchart-node.selected .flowchart-node-shape {
+ stroke: #2563eb !important;
+ stroke-width: 2.25;
+ }
+ .flowchart-edge {
+ cursor: pointer;
+ }
+ .flowchart-edge:hover {
+ stroke: #2563eb !important;
+ }
+ .flowchart-edge.selected {
+ stroke: #2563eb !important;
+ stroke-width: 2.5;
+ }
+ /* Resize handle — larger invisible hit area + visible square. */
+ .flowchart-resize-handle {
+ cursor: nwse-resize;
+ }
+ .flowchart-resize-handle-hit {
+ fill: transparent;
+ stroke: none;
+ }
+ .flowchart-resize-handle-grip {
+ fill: #2563eb;
+ stroke: #1e40af;
+ stroke-width: 1;
+ }
+ /* Edge label background — keeps labels legible across curves by
+ giving them an opaque white pill behind the text. */
+ .flowchart-edge-label-bg {
+ fill: #ffffff;
+ stroke: #d1d5db;
+ stroke-width: 0.5;
+ }
+ /* Modal dialog — fade + scale-in entrance. */
+ .fc-modal {
+ animation: fc-modal-in 0.15s ease-out;
+ }
+ @keyframes fc-modal-in {
+ from {
+ opacity: 0;
+ transform: translate(-50%, -50%) scale(0.96);
+ }
+ to {
+ opacity: 1;
+ transform: translate(-50%, -50%) scale(1);
+ }
+ }
+ .fc-modal-overlay {
+ animation: fc-overlay-in 0.12s ease-out;
+ }
+ @keyframes fc-overlay-in {
+ from {
+ opacity: 0;
+ }
+ to {
+ opacity: 1;
+ }
+ }
/* v4.10.0 — preview-render info card explaining the layout */
.fc-preview-render-note {
font-size: 0.75rem;
diff --git a/src/flowchart/flowchart-canvas.js b/src/flowchart/flowchart-canvas.js
index cfb4441..bfe201b 100644
--- a/src/flowchart/flowchart-canvas.js
+++ b/src/flowchart/flowchart-canvas.js
@@ -232,21 +232,29 @@ function createCanvas(container, store, opts = {}) {
// v4.13.0 — bottom-right resize handle on the selected node. A
// single square handle is enough for v1; multi-handle (4 corners
// + 4 edges) is a follow-up. Width is the only mutable dimension.
+ // Two rects: a larger transparent hit area (24px) so the handle is
+ // easier to grab, plus a smaller visible grip (10px) styled via CSS.
if (node.id === selectedNodeId) {
- const handleSize = 10;
- const handle = svgEl('rect', {
- x: w - handleSize / 2,
- y: DEFAULT_HEIGHT - handleSize / 2,
- width: handleSize,
- height: handleSize,
- fill: '#e5461f',
- stroke: '#ffffff',
- 'stroke-width': 1,
- class: 'flowchart-resize-handle',
+ const gripSize = 10;
+ const hitSize = 24;
+ const hit = svgEl('rect', {
+ x: w - hitSize / 2,
+ y: DEFAULT_HEIGHT - hitSize / 2,
+ width: hitSize,
+ height: hitSize,
+ class: 'flowchart-resize-handle flowchart-resize-handle-hit',
'data-resize-node': node.id,
- cursor: 'nwse-resize',
});
- g.appendChild(handle);
+ const grip = svgEl('rect', {
+ x: w - gripSize / 2,
+ y: DEFAULT_HEIGHT - gripSize / 2,
+ width: gripSize,
+ height: gripSize,
+ rx: 2,
+ class: 'flowchart-resize-handle flowchart-resize-handle-grip',
+ });
+ g.appendChild(hit);
+ g.appendChild(grip);
}
nodesLayer.appendChild(g);
diff --git a/tests/flowchart-align.test.js b/tests/flowchart-align.test.js
index fb9fbbf..f51074e 100644
--- a/tests/flowchart-align.test.js
+++ b/tests/flowchart-align.test.js
@@ -91,11 +91,7 @@ describe('flowchart-align: distributeHorizontally', () => {
expect(out.map((node) => node.x)).toEqual([0, 300, 600, 900]);
});
test('handles unsorted input by sorting first', () => {
- const out = distributeHorizontally([
- n('a', 500, 0),
- n('b', 0, 0),
- n('c', 900, 0),
- ]);
+ const out = distributeHorizontally([n('a', 500, 0), n('b', 0, 0), n('c', 900, 0)]);
// sorted: 0, 500, 900 → gap = 450 → x = [0, 450, 900]
expect(out.map((node) => node.x)).toEqual([0, 450, 900]);
});
@@ -109,12 +105,7 @@ describe('flowchart-align: distributeHorizontally', () => {
describe('flowchart-align: distributeVertically', () => {
test('spaces 4 nodes evenly between topmost and bottommost', () => {
- const out = distributeVertically([
- n('a', 0, 0),
- n('b', 0, 60),
- n('c', 0, 300),
- n('d', 0, 900),
- ]);
+ const out = distributeVertically([n('a', 0, 0), n('b', 0, 60), n('c', 0, 300), n('d', 0, 900)]);
// gap = 900 / 3 = 300
expect(out.map((node) => node.y)).toEqual([0, 300, 600, 900]);
});