From ea5bd5bfd7f6d41c64319847597894e61a61f126 Mon Sep 17 00:00:00 2001 From: Adam Soltys Date: Wed, 2 Sep 2026 20:17:27 -0700 Subject: The black flash on Get started dies at the morph: a reused button whose class changes between screens is a different control wearing the same node, and its background transition was crossfading the old style into the new one — repaints aren't style animations, so the swap now snaps and the transition comes back after the paint MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Fable 5 Claude-Session: https://claude.ai/code/session_01MrkLsNScXe9b6BviUSdmMr --- src/app.js | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'src') diff --git a/src/app.js b/src/app.js index 4e69eb7..a48a7d9 100644 --- a/src/app.js +++ b/src/app.js @@ -169,8 +169,18 @@ function morph(a, b) { return; } // attributes (className and style strings ride along as attributes) + // A reused BUTTON whose class changes is a different control wearing the + // same node (screens lining up positionally) — its `transition: background` + // would visibly crossfade the old style into the new one (a dark filled + // button melting into a text link read as a black flash). Repaints aren't + // style animations: snap it, restore the transition after the paint. + const snap = a.nodeName === 'BUTTON' && a.getAttribute('class') !== b.getAttribute('class'); for (const at of [...a.attributes]) if (!b.hasAttribute(at.name)) a.removeAttribute(at.name); for (const at of [...b.attributes]) if (a.getAttribute(at.name) !== at.value) a.setAttribute(at.name, at.value); + if (snap) { + a.style.transition = 'none'; + requestAnimationFrame(() => requestAnimationFrame(() => { a.style.transition = ''; })); + } // event handler slots claimed via h() if (a._evs) for (const n of a._evs) if (!(b._evs && b._evs.has(n))) a[n] = null; if (b._evs) for (const n of b._evs) a[n] = b[n]; -- cgit v1.2.3