The owner tunes the ease, and a cue button answers the press (#175) - #176
The owner tunes the ease, and a cue button answers the press (#175)#176Devski wants to merge 2 commits into
Conversation
Three things Dawid asked for after using #153, all in how the motion is controlled rather than in what it does. **The ease is two amounts, not a switch.** `easeIn` and `easeOut`, each 0..1 and each absent meaning 1, live beside the glide in `r360_params` — JSON, so no migration. The curve is a blend between the straight line and the smoothstep #153 shipped, taken per half around the point they share: full both ways IS that smoothstep rather than an approximation of it, so every work saved before the sliders existed feels exactly as it did, and each half slides towards a straight line on its own. 1 in and 0 out gathers pace and then runs flat into its frame. **One curve for every travel.** `travelCurve(params)` is read once in the hook and handed to `travelAlong`, which is what the ring, a marker on it and a cue button all call — so no hand can acquire a feel of its own. The click Dawid meant is the one on the navigation ring, and it goes through there. **The cue row answers the press.** It was lighting `cue.frame === orbit.frame` — a readout of where the orbit IS, which meant a press did nothing visible until the orbit arrived, and that every cue a travel crossed lit for the 28 ms it stood there. The orbit now says where it was ASKED to be (`aimedAt`), and the row reads that: lit on the press, dropped when a hand takes over, and the cues on the way stay unlit. What they do instead is pulse — a ring that grows and fades, never the tones, which cannot fade between each other without passing through colours that cannot be read (#107, caught by axe). Reduced motion turns it off. **And every button in the product now says it is pressable.** Tailwind 4's preflight no longer sets `cursor: pointer` and the shared Button base never did, so all of them showed the plain arrow. One base rule, disabled ones kept as they were. The new e2e case earned itself: `run` begins by cancelling the travel in flight, and cancelling is what drops the aim — so the aim set before it was cleared a line later, and the button lit only on arrival, exactly the bug this was meant to remove. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The curve came back sound; the cue row did not, and none of it was visible to a green suite — nothing asserted the pulse, and the e2e stubs out the animation frames the pulse lives between. - **The pressed button pulsed at the end of every travel.** `travelStop` stands the orbit on its last frame well before it arrives — a fifth of the way from the end on a full ease — so the destination was "crossed" while it was also "here": a focus-coloured ring running over the solid tone and then cut off. The frame being aimed at is exempt now. - **The pulse was never seen anywhere else.** It was derived from the current frame, which is one animation frame wide — 28 ms, less through the fast middle of a travel — while the animation is 450 ms, and taking the attribute away cuts the animation off. That is the same blink moved from the fill to a shadow. Crossings are latched now and cleared on animationend, so each one plays out. - **A coast still marked every cue it passed.** It goes through `run` directly, so nothing was aimed at, and the row fell back to the current frame: the solid tone for one frame on every cue a thrown orbit crossed — the longest motion there is, on the gesture a phone uses most. The orbit now says whether it is `moving` at all, and while it is, a frame with nobody asking for it is passed through rather than arrived at. Also from the review: the curve object is memoised, exactly as the comment three lines above it demands of the glide; `alongCurve` clamps what it is handed, because the type is exported and an amount of 5 bends the blend back down the path and hands out a frame that is not a number; a slider dragged back to full writes nothing at all, so a work is as untouched as it was found; the sliders step by whole percent, which the schema accepts, rather than by ten, which native validation would refuse on save; the cursor rule covers a button disabled with aria-disabled; and the motion hint names the two sliders that now sit under it. The comment claiming no step in the middle said more than it could: the POSITION is continuous there, the speed is not, and the asymmetric settings are exactly the ones that show it. It says that now. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
A review lane went over this. The curve came back sound — the blend is monotone for every pair of amounts, continuous at the midpoint, and The pressed button pulsed at the end of every travel. The pulse was never seen on the cues it was for. It was derived from the current frame, which lasts one animation frame — 28 ms, less through the fast middle of an eased travel, which is exactly where crossings happen — while the animation is 450 ms, and removing the attribute removes the animation outright. So it played about 6% of its ease-out: a 1 px ring for 28 ms. That is the same blink, moved from the fill to a shadow. Crossings are latched in state now and cleared on A thrown orbit still marked every cue it passed. A coast calls Also applied: the curve object is memoised (the comment three lines above it demands precisely that of the glide, and One comment was claiming more than it could: the position is continuous at the midpoint, the speed is not — 100 in and 0 out drops a third of the pace there. It says so now, as a thing the owner chose rather than a seam to hide. Noted and not changed: |
|
Closed unmerged on Dawid's decision of 12.09.2026: the product is losing functions rather than gaining them, and this added three. Nothing of it reached Kept in the record because it is a real finding either way: Tailwind 4 no longer sets |
Closes #175.
Three things Dawid asked for after using #153 — all about how the motion is controlled, not what it does.
The ease is two amounts, not a switch
easeInandeaseOut, each 0..1, each absent meaning 1, beside the glide inr360_params— JSON, so no migration. Two sliders under the motion switch in the edit form (Rozbieg / Dobieg), shown as whole percent.The curve is a blend between the straight line and the smoothstep #153 shipped, applied per half around the point the two agree on. That choice does the work:
One curve for every travel
travelCurve(params)is read once in the hook and handed totravelAlong— which is what a click on the ring, a click on a marker, and a press on a cue button all call. No hand can acquire a feel of its own. The click Dawid meant is the one on the navigation ring, and it goes through there.The cue row answers the press, not the arrival
It was lighting
cue.frame === orbit.frame— a readout of where the orbit is. Two consequences, both of them Dawid's complaints: a press did nothing visible until the orbit arrived, and every cue a travel crossed lit for the 28 ms the orbit stood on it — a blink.The orbit now says where it was asked to be (
aimedAt, set only by an aimed travel — a coast has an end, but nobody asked for it), and the row reads that: lit on the press, dropped the moment a hand takes over, and the cues on the way stay unlit.What they do instead is pulse — a ring that grows and fades. Never the tones: this row deliberately has no colour transition because a fade between them passes through colours that cannot be read, which axe caught in the lightbox on #107.
prefers-reduced-motionturns the pulse off.Every button now says it is pressable
Tailwind 4's preflight no longer sets
cursor: pointeronbutton(verified innode_modules/tailwindcss/preflight.css, 4.3.3) and the sharedButtonbase never did — so every button in the product showed the plain arrow. Dawid noticed it on the cue row; it was true of all of them. One base rule; disabled buttons keep the cursor that says so.Verified
pnpm checkgreen,pnpm buildgreen (thedata-passingvariant and the keyframe are in the generated CSS, with the reduced-motion rule beside them).r360.spec.ts10/10 andworks.spec.ts11/11 against the test database;orbit.test.tscovers the new curve — each amount bending its own half, 0/0 matching a constant pace frame for frame, a value out of range or absent reading as the full ease, and the switch still winning over both.The new e2e case earned itself immediately:
runbegins by cancelling the travel in flight, and cancelling is what drops the aim — so an aim set before that call was cleared a line later and the button lit only on arrival, which is precisely the bug this was meant to remove.🤖 Generated with Claude Code