Skip to content

Commit 3f1b62d

Browse files
author
Fergus Bisset
committed
fix(product-card): prevent hydration precision mismatches by formatting SVG numeric attributes with fixed precision (toFixed(2))
1 parent 9410a80 commit 3f1b62d

File tree

1 file changed

+21
-16
lines changed

1 file changed

+21
-16
lines changed

src/components/ProductCard/ProductCard.tsx

Lines changed: 21 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,9 @@ const VectorGraphic: React.FC<{
203203
const viewW = baseHeight * aspectRatio;
204204
const viewH = baseHeight;
205205

206+
// Format numbers deterministically to avoid SSR/client attribute string diffs
207+
const fmt = (n: number) => n.toFixed(2);
208+
206209
const hexPoints = (cx: number, cy: number, size: number): string => {
207210
// Hexagon points in proper coordinates
208211
const r = size / 2;
@@ -212,7 +215,7 @@ const VectorGraphic: React.FC<{
212215
const rad = (a * Math.PI) / 180;
213216
const x = cx + r * Math.cos(rad);
214217
const y = cy + r * Math.sin(rad);
215-
return `${x},${y}`;
218+
return `${fmt(x)},${fmt(y)}`;
216219
})
217220
.join(" ");
218221
};
@@ -406,13 +409,13 @@ const VectorGraphic: React.FC<{
406409
return (
407410
<line
408411
key={`connector-${i}-${j}`}
409-
x1={best.p[0]}
410-
y1={best.p[1]}
411-
x2={best.q[0]}
412-
y2={best.q[1]}
412+
x1={fmt(best.p[0])}
413+
y1={fmt(best.p[1])}
414+
x2={fmt(best.q[0])}
415+
y2={fmt(best.q[1])}
413416
stroke="rgb(158, 171, 181)"
414-
strokeWidth="0.5"
415-
strokeMiterlimit="0.5"
417+
strokeWidth={fmt(0.5)}
418+
strokeMiterlimit={fmt(0.5)}
416419
/>
417420
);
418421
});
@@ -432,6 +435,8 @@ const VectorGraphic: React.FC<{
432435
// No scaling needed - shapes use their natural sizes
433436
const x = (shape.x / 100) * viewW;
434437
const y = (shape.y / 100) * viewH;
438+
const xStr = fmt(x);
439+
const yStr = fmt(y);
435440

436441
if (shape.kind === VectorGraphicKindEnum.Rect) {
437442
// Rectangles use their specified dimensions directly
@@ -441,11 +446,11 @@ const VectorGraphic: React.FC<{
441446
<rect
442447
key={idx}
443448
className={fillClass}
444-
x={x - w / 2}
445-
y={y - h / 2}
446-
width={w}
447-
height={h}
448-
transform={`rotate(${shape.rotate || 0} ${x} ${y})`}
449+
x={fmt(x - w / 2)}
450+
y={fmt(y - h / 2)}
451+
width={fmt(w)}
452+
height={fmt(h)}
453+
transform={`rotate(${shape.rotate || 0} ${xStr} ${yStr})`}
449454
filter={filter}
450455
/>
451456
);
@@ -456,9 +461,9 @@ const VectorGraphic: React.FC<{
456461
<circle
457462
key={idx}
458463
className={fillClass}
459-
cx={x}
460-
cy={y}
461-
r={r}
464+
cx={xStr}
465+
cy={yStr}
466+
r={fmt(r)}
462467
filter={filter}
463468
/>
464469
);
@@ -470,7 +475,7 @@ const VectorGraphic: React.FC<{
470475
key={idx}
471476
className={fillClass}
472477
points={hexPoints(x, y, size)}
473-
transform={`rotate(${shape.rotate || 0} ${x} ${y})`}
478+
transform={`rotate(${shape.rotate || 0} ${xStr} ${yStr})`}
474479
filter={filter}
475480
/>
476481
);

0 commit comments

Comments
 (0)