From eb13689ae79f9baddf973c1dc0a744913490f535 Mon Sep 17 00:00:00 2001 From: c0mrade Date: Tue, 26 May 2026 20:27:47 +0300 Subject: [PATCH] perf(motion): convert layout-property transitions to transforms MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Audit P1: 5 of 7 layout-property animations were transition-[width] or transition-[left] — these trigger reflow + repaint every frame. Convert to transform-based equivalents that run on the compositor. Subscription.tsx — 3 progress bars + 1 toggle: • Device usage bar (track w-16) — width % → scaleX with a 0.0625 floor (= 4px on 64px track) preserving the minWidth: 4px guard when connectedDevices > 0. • Traffic-purchase progress — absolute inset-0 + width % → transform: scaleX with origin-left, gradient stretches with the fill same as before. • Subscription period progress — same conversion. • Autopay toggle thumb — left: 3↔26px → translateX(0↔23px) with fixed left: 3px. role='switch' + aria-checked unchanged. globals.css — .progress-fill utility class: • transition-property: width, background-color → transform, background-color. Width set to w-full + origin-left so consumers just set transform: scaleX(0..1). Currently has no .tsx consumers (grep clean) but the API stays valid for future use. Skipped (bounded one-shot, transform alternative has tradeoffs): • Info.tsx + InfoPageView.tsx accordion height. Animating from 0 to content-driven scrollHeight needs layout one way or another — grid-template-rows 0fr/1fr and max-height also layout-class properties; transform: scaleY squishes text contents. Cost is bounded: one animation per user click, not continuous, not on critical path. Separate work if priority changes. Visual parity: scaleX renders identical geometry to width % on the inner fill. box-shadow on the device bar (0 0 8px 40) scales proportionally — tiny visual difference at full width, none visible at partial widths. --- src/pages/Subscription.tsx | 28 +++++++++++++++++++--------- src/styles/globals.css | 6 ++++-- 2 files changed, 23 insertions(+), 11 deletions(-) diff --git a/src/pages/Subscription.tsx b/src/pages/Subscription.tsx index 5cb6a20..ba083b6 100644 --- a/src/pages/Subscription.tsx +++ b/src/pages/Subscription.tsx @@ -997,13 +997,18 @@ export default function Subscription() { className="h-[6px] w-full overflow-hidden rounded-full" style={{ background: g.textGhost }} > + {/* scaleX (compositor) instead of width (layout-thrash). + Track is 64px (w-16), so 0.0625 floor = 4px minimum, + preserving the prior minWidth behaviour. */}
{ + const pct = connectedDevices / subscription.device_limit; + return connectedDevices > 0 ? Math.max(pct, 0.0625) : 0; + })()})`, background: zone.mainHex, boxShadow: `0 0 8px ${zone.mainHex}40`, - minWidth: connectedDevices > 0 ? '4px' : '0px', }} />
@@ -1146,9 +1151,9 @@ export default function Subscription() { style={{ background: g.trackBg }} >
@@ -1193,10 +1198,15 @@ export default function Subscription() { background: subscription.autopay_enabled ? zone.mainHex : g.textGhost, }} > + {/* translateX (compositor) instead of left (layout-thrash). + Resting position pinned at left:3px; on toggles a 23px + slide on the GPU. */} @@ -1387,9 +1397,9 @@ export default function Subscription() { style={{ background: g.trackBg }} >