diff --git a/.changeset/pin-dots-svg.md b/.changeset/pin-dots-svg.md new file mode 100644 index 0000000..33f4a95 --- /dev/null +++ b/.changeset/pin-dots-svg.md @@ -0,0 +1,8 @@ +--- +"pointsy": patch +--- + +Render the PIN dots as SVG circles. Styled HTML elements for the dots could fail +to paint on some real iOS devices even when they rendered fine everywhere else; +SVG ``s render identically across devices, so the four dots now always +show (empty = muted sage, filled = emerald, wrong attempt = rose + shake). diff --git a/components/auth/PinPad.tsx b/components/auth/PinPad.tsx index 3b3d0f9..c66a8b1 100644 --- a/components/auth/PinPad.tsx +++ b/components/auth/PinPad.tsx @@ -81,13 +81,20 @@ export function PinPad({

{label}

- s could collapse to nothing on + real iOS). */} + ))} + + + {pin.length} of {length} digits entered
{KEYS.map((k) => ( diff --git a/components/auth/pin-pad.module.css b/components/auth/pin-pad.module.css index 04dcdea..7b80074 100644 --- a/components/auth/pin-pad.module.css +++ b/components/auth/pin-pad.module.css @@ -11,45 +11,34 @@ color: var(--color-text); } +/* The dots are an of s (see PinPad) — bulletproof on real iOS, + where empty CSS-sized HTML elements could collapse to nothing. */ .dots { - display: flex; - justify-content: center; - gap: var(--space-3); - /* Reserve the row's height so the area never collapses to nothing. */ - min-height: 20px; + display: block; + width: 8rem; + height: auto; + margin: 0 auto; + overflow: visible; } -/* - * Bulletproof on real iOS: SOLID filled circles (no border / box-sizing), and - * `flex: 0 0 20px` so empty flex items can never shrink to nothing — the fragile - * empty-span-with-border construct rendered fine in desktop WebKit but vanished - * on-device. - */ .dot, .dotFilled, .dotError { - flex: 0 0 20px; - width: 20px; - height: 20px; - border-radius: 999px; - transition: - background-color 0.12s ease, - transform 0.12s ease; + transition: fill 0.12s ease; } -/* Empty slot: a clearly visible muted-sage dot. */ +/* Empty slot: a clearly visible muted-sage circle. */ .dot { - background: var(--color-text-faint); + fill: var(--color-text-faint); } -/* Entered: solid emerald, slightly larger so filling is obvious. */ +/* Entered: solid emerald. */ .dotFilled { - background: var(--color-primary); - transform: scale(1.1); + fill: var(--color-primary); } .dotError { - background: var(--color-danger); + fill: var(--color-danger); } /* Wrong-attempt flash: shake the dot row so the rejection is unmissable. */