Spaces:
Sleeping
Turn the ambient panel float off by default
Browse filesBisected against the user's report that the button used to work. Same
save test, run repeatedly:
c9d9189 "motion runtime + icons 1.0" save works 3/3
48fd5c7 "UI: 3D depth layer ..." save FAILS 0/4
float off (this commit) save works 4/4
The regression entered with the 3D depth layer. Its ambient float never
settles, and a surface that never settles carries its buttons out from
under the pointer -- a click fires only when mousedown and mouseup land
on the same element, so the press registers and nothing happens, which
is exactly how it was reported.
Freezing the float near the pointer fixes this in principle and in every
automated test here, but it did not hold in the user's hands across
three attempts, so the working button wins over the effect. The
proximity-freeze machinery is kept intact behind the flag.
UPS_PANEL_FLOAT=1 restores the drift. Only that one effect is gated:
aurora, motes, entrances, sheen, press, hover lift, card tilt, ring
draw and counters all still run (verified: 6 live web animations and 5
CSS animations after the change, 0 perpetual floats).
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
- app/ui/motion_runtime.py +27 -0
|
@@ -69,6 +69,22 @@ _DRIVER = r"""
|
|
| 69 |
var M = window.Motion;
|
| 70 |
if (!M || !M.animate) return;
|
| 71 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 72 |
var EASE = [0.22, 0.61, 0.36, 1];
|
| 73 |
var SPRING = { type: 'spring', stiffness: 320, damping: 30, mass: 0.9 };
|
| 74 |
var reduce = false;
|
|
@@ -140,6 +156,11 @@ _DRIVER = r"""
|
|
| 140 |
// long as the node lives, so nothing else may clear it. Anything that wants
|
| 141 |
// the transform (hover, press, tilt) pauses this first and resumes after.
|
| 142 |
function float3d(el, i) {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 143 |
if (!canMove(el)) return;
|
| 144 |
depthParent(el);
|
| 145 |
el.style.transformStyle = 'preserve-3d';
|
|
@@ -570,6 +591,11 @@ def inject() -> None:
|
|
| 570 |
reduce_motion = (os.getenv("UPS_REDUCE_MOTION", "") or "").strip().lower() in (
|
| 571 |
"1", "true", "yes", "on"
|
| 572 |
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 573 |
components.html(
|
| 574 |
# The payloads come first: the bootstrap below reads them by id, and a
|
| 575 |
# <script> only sees the document that exists above it.
|
|
@@ -586,6 +612,7 @@ def inject() -> None:
|
|
| 586 |
" var w = window.parent, d = w.document;\n"
|
| 587 |
" if (!d || !d.head) return false;\n"
|
| 588 |
" w.__upsReduceMotion = " + ("true" if reduce_motion else "false") + ";\n"
|
|
|
|
| 589 |
" if (!w.Motion) {\n"
|
| 590 |
" var s = d.createElement('script');\n"
|
| 591 |
" s.id = 'ups-motion-lib';\n"
|
|
|
|
| 69 |
var M = window.Motion;
|
| 70 |
if (!M || !M.animate) return;
|
| 71 |
|
| 72 |
+
// The ambient panel float — the perpetual translateZ/rotate loop added in
|
| 73 |
+
// "UI: 3D depth layer" — is OFF unless UPS_PANEL_FLOAT is set.
|
| 74 |
+
//
|
| 75 |
+
// It is the one effect that never settles, and a surface that never settles
|
| 76 |
+
// drags its buttons out from under the pointer: a click fires only when
|
| 77 |
+
// mousedown and mouseup land on the same element. Measured against that
|
| 78 |
+
// commit, Save Configuration failed to save on 4 of 4 attempts; on the
|
| 79 |
+
// commit before it, and with the float off, it saves every time.
|
| 80 |
+
//
|
| 81 |
+
// Freezing it near the pointer (below) fixes this in principle and in every
|
| 82 |
+
// automated test, but not reliably in the hand, so the working button wins
|
| 83 |
+
// over the effect. Set UPS_PANEL_FLOAT=1 to bring the drift back — the
|
| 84 |
+
// proximity-freeze machinery below stays in place for that case.
|
| 85 |
+
var FLOAT_ON = false;
|
| 86 |
+
try { FLOAT_ON = !!window.__upsPanelFloat; } catch (e) {}
|
| 87 |
+
|
| 88 |
var EASE = [0.22, 0.61, 0.36, 1];
|
| 89 |
var SPRING = { type: 'spring', stiffness: 320, damping: 30, mass: 0.9 };
|
| 90 |
var reduce = false;
|
|
|
|
| 156 |
// long as the node lives, so nothing else may clear it. Anything that wants
|
| 157 |
// the transform (hover, press, tilt) pauses this first and resumes after.
|
| 158 |
function float3d(el, i) {
|
| 159 |
+
// OFF by default — see FLOAT_ON. This is the single choke point for the
|
| 160 |
+
// perpetual drift, so gating here leaves every other piece of the motion
|
| 161 |
+
// layer (entrances, press, hover lift, tilt on presentation cards, sheen,
|
| 162 |
+
// ring draw, counters) running exactly as designed.
|
| 163 |
+
if (!FLOAT_ON) return;
|
| 164 |
if (!canMove(el)) return;
|
| 165 |
depthParent(el);
|
| 166 |
el.style.transformStyle = 'preserve-3d';
|
|
|
|
| 591 |
reduce_motion = (os.getenv("UPS_REDUCE_MOTION", "") or "").strip().lower() in (
|
| 592 |
"1", "true", "yes", "on"
|
| 593 |
)
|
| 594 |
+
# Opt-in for the perpetual panel drift. Off by default because it moves
|
| 595 |
+
# buttons out from under a click; see FLOAT_ON in the driver.
|
| 596 |
+
panel_float = (os.getenv("UPS_PANEL_FLOAT", "") or "").strip().lower() in (
|
| 597 |
+
"1", "true", "yes", "on"
|
| 598 |
+
)
|
| 599 |
components.html(
|
| 600 |
# The payloads come first: the bootstrap below reads them by id, and a
|
| 601 |
# <script> only sees the document that exists above it.
|
|
|
|
| 612 |
" var w = window.parent, d = w.document;\n"
|
| 613 |
" if (!d || !d.head) return false;\n"
|
| 614 |
" w.__upsReduceMotion = " + ("true" if reduce_motion else "false") + ";\n"
|
| 615 |
+
" w.__upsPanelFloat = " + ("true" if panel_float else "false") + ";\n"
|
| 616 |
" if (!w.Motion) {\n"
|
| 617 |
" var s = d.createElement('script');\n"
|
| 618 |
" s.id = 'ups-motion-lib';\n"
|