Repository navigation
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
AI review status for this pull request.
|
There was a problem hiding this comment.
Approval of this spec change waits on an engineering owner's decision on the proposed motion direction in spec:AST-108 FR3a, FR8, DEC-3 and DEC-4. Those clauses replace each gesture's measured release spring with one spring per character at the default, move touch entrances and the animated-layout glide onto the token table, and add 'fluid'. That decision also covers the amendments they need to AST-108 FR1/FR3/FR5, AST-094 FR1/FR4 and AST-105 FR4. An engineering owner records it by commenting /approve-spec <full head SHA> on this pull request; the author may do so as an engineering owner.
Separately from that decision, the record needs these fixes:
- The FR8 verification row (line 264) still fails "a glide that plays a curve" and "a touch role off its measured value", although FR8 and FR3a now have the glide and touch entrances play the token table.
- The settle-time definition (lines 187–190) does not match 347 ms for
springs.menuOpen: by "stays within 1 %" the spring settles at about 324 ms, where the fluid entrance curve is about 6 % off, so state the envelope-bound window the 347 ms comes from. - FR1, FR3 and FR5 and their verification rows still say three characters, measured springs at
'standard', and unchanged existing themes, so rewrite them here (marked proposed) instead of noting that approval amends them. - The Current-state impact should also list
architecture:theme-authoring-contractINV15, AST-094 FR1 and AST-105 FR4 as records to amend, not only AST-094 FR4. - The Reduce Motion bullet (lines 205–206) lands every non-touch release at once, but the reduced-motion design record cross-fades a trackpad-started release on a coarse primary pointer.
[Automated review]
| | FR5 | Theme tests with the released configurations | a `MotionScaleConfig` theme, explicit tokens, an extending theme; an adaptation rule that sets `tempo` or `character` | changed output for an existing theme, or a knob that beats an explicit field, fails | | ||
| | FR6 | Server-render tests and import checks | a server render with each `reducedMotion`; importing the theme and motion modules; `'always'` with the person's setting off, across components that key on `prefers-reduced-motion`; a nested theme under an `'always'` theme | a DOM access at import or on the server, theme CSS emitted for `'system'`, a hydration change, or a component style, script reader, or `when: {motion}` rule that ignores the root mark under `'always'`, or a nested theme that restores motion under an ancestor's `'always'`, fails | | ||
| | FR7 | Docs review | each listed doc | a doc without the knobs, the fixed list, or the precedence fails | | ||
| | FR8 (proposed) | Theme unit tests over generated CSS, resolver tests, and browser frame capture | `'fluid'` at each `tempo` bound and 1; each table row; a glide under a mouse and a finger; Reduce Motion under a coarse and a fine pointer | a fluid curve more than 2 % of the travel off its spring, a CSS exit, fade, or duration token that differs from `'standard'`, a touch role off its measured value, a glide that plays a curve, or a spring under Reduce Motion fails | |
There was a problem hiding this comment.
This row still fails "a touch role off its measured value" and "a glide that plays a curve", but FR8's token table (line 173), the impact line at 242–244 and FR3a (103–107) now have the glide play --ease-move and non-gesture touch roles play the token table. Suggest "a glide that plays a spring" and "a fluid gesture spring off its measured value".
| - A fluid curve is its spring's travel from rest over the spring's 99 % | ||
| settle time (the time after which it stays within 1 % of its travel: | ||
| 347 ms for `springs.menuOpen`, 528 ms for `springs.settle`), fitted as a | ||
| cubic Bézier within 2 % of the travel at every point. The spring's |
There was a problem hiding this comment.
By "the time after which it stays within 1 % of its travel", springs.menuOpen (response 0.32 s, damping ratio 0.8) settles at about 324 ms. 347 ms is the decay-envelope bound the spring model's settle time returns. Over 324 ms, cubic-bezier(0.31, 0.35, 0.12, 1.12) is about 6 % off the spring, beyond the 2 % bound, so a test built from this definition rejects the table's curve. Define the window as the envelope bound, or state 347 ms without the gloss.
| - FR3a and FR8 are proposed. When approved, they amend FR1 (a fourth | ||
| `character`), FR3 (at `'standard'`, a gesture plays the standard gesture | ||
| spring, not its measured one, and a non-gesture motion plays the token | ||
| table on every pointer), and FR5 (an existing theme's gesture springs and | ||
| touch timed motion change with that default); `spec:AST-094` FR4 states the | ||
| pointer side. |
There was a problem hiding this comment.
FR1 (line 65), FR3 (90–92: "every role plays its measured value exactly"), FR5 (134–135: "springs included") and their verification rows (257, 261) still say the opposite of FR8's standard gesture spring. Approving this head would approve both. Rewrite those clauses and rows here, marked proposed.
| - `defineTheme` does not accept `'fluid'` yet. It needs `spec:AST-105` FR4 to | ||
| time the glide from the theme's tokens, the animator to read the theme's | ||
| knobs at each gesture's start, and the character's curve table to set | ||
| `--ease-entrance` and `--ease-move` to different values. Today the glide | ||
| plays `springs.settle` at every character, no spring reads the knobs, and | ||
| no Core component reads `--ease-entrance` or `--ease-move`. |
There was a problem hiding this comment.
architecture:theme-authoring-contract INV15 (three characters), AST-094 FR1 ("MUST default to the measured native value") and AST-105 FR4 (the glide reads springs.settle) also need amending for FR3a and FR8. Please list them with the change each needs.
| - Reduce Motion is the same at every character (`design:reduced-motion` | ||
| DR1–DR3): no spring plays and nothing travels; a coarse primary pointer | ||
| gets a cross-fade of 200 ms or less, any other pointer an immediate | ||
| change; a throw still coasts, and a release that snaps, dismisses, or | ||
| pages cross-fades after a touch drag and lands at once otherwise. |
There was a problem hiding this comment.
"lands at once otherwise" departs from the reduced-motion design record, which has a release a trackpad started follow DR2 (cross-fade) on a coarse primary pointer. Suggest "cross-fades after a touch drag or under a coarse primary pointer, and lands at once otherwise", or cite DR2 and DR3 without restating them.
People using a theme with
character: 'fluid'get motion that feels like the native platform: a flick keeps its speed into a measured spring, and entrances and moves take curves fitted to those springs. Every other character gets the same split, with its own curves and its own gesture spring.Draft, stacked on
main. This pull request introduces'fluid'as the fourthcharacter: the type value, both tables, and the gesture springs. It depends on #9663, which makes the theme'scharacterandtemporeach the glide; it does not touch #9663's branch. Off the release path: this spec merges on its own, no release gate, plan, or changeset depends on it, and the build lands whenever it is ready.Exact decision needed
What each
characterpresets: the token table that non-gesture motion plays, and the spring that gesture motion plays, and what'fluid'puts in both.Existing authority searched
spec:AST-108FR1–FR5, FR4a, DEC-1: three characters reach--ease-entrance,--ease-move, and the springs' bounce; exits and--ease-standardnever change;temposcales every duration.spec:AST-105FR4, FR8, FR9: the glide, swap, and edge reveal share one motion.spec:AST-094FR4, FR36–FR38, FR43: the measured springs, the release settle, and gestures on every pointer. Its pointer-side wording is written in a separate pull request.design:reduced-motionDR1–DR3.motion/uikit/springs.ts,theme/themeMotion.ts(CHARACTER_EASE),theme/motionKnobs.ts,motion/animatedLayout.ts(the glide's CSS twin).characterandtempo; adds no character); feat(core): the animator's springs follow the theme's tempo and character #8677 (the animator readstempoandcharacterat each motion's start).Decision
Gesture motion plays a spring; other motion plays the tokens (FR3a). On every pointer and at every character, the settle, snap, dismissal, or page after a drag, swipe, flick, or pan starts from the gesture's velocity on a spring.
charactersets its bounce and response;temposcales its duration. Every other timed motion, the glide, swap, and edge reveal included, plays the character's easing token over its duration token. Finger tracking, momentum, and the rubber band stay fixed.Each character is two tables (FR8).
--ease-entrancecubic-bezier(0, 0, 0.2, 1)cubic-bezier(0.24, 1, 0.4, 1)cubic-bezier(0.3, 1.2, 0.5, 1)cubic-bezier(0.31, 0.35, 0.12, 1.12)(menu spring's shape)--ease-movecubic-bezier(0.23, 0.17, 0.2, 0.99)(settle spring's shape)--ease-exit--ease-standard--duration-*How the fluid curves are made. Each is its spring's travel from rest over the spring's 99 % settle time (347 ms for the menu spring, 528 ms for the settle spring), fitted as a cubic Bézier: maximum error 1.9 % and 1.4 % of the travel. A cubic Bézier keeps the token's current form and works in every browser;
linear()would add nothing visible at that error.How the gesture springs are made. From rest, each crisp, standard, and expressive spring stays within 1 % of its travel after
--duration-medium-min(310 ms), the glide's length. Standard does not overshoot, crisp is overdamped, expressive overshoots about 1.5 %, as its curve does.Reduce Motion is the same at every character: no spring, no travel; a cross-fade of 200 ms or less under a coarse pointer, an immediate change otherwise; a throw still coasts.
No engine switch. The glide, swap, and edge reveal are non-gesture motion, so at
'fluid'they play fluid's spring-shaped move token over--duration-medium-min, the same way they play every other character's token (spec(AST-105, AST-108): glides follow the theme's character and tempo; the measured spring becomes character 'native' #9663). No character switches non-gesture motion to the spring engine.Rejected alternatives
tempoalready owns length.Claim scope and non-goals
--ease-exit,--ease-standard, the duration scale, the press clocks, or the fixed list.spec:AST-094's pointer wording is out of scope here.Evidence and implementation relationship
Values computed from the springs' closed forms (SwiftUI duration and bounce, response and damping ratio), settle time at 1 % of travel, and a cubic-Bézier fit minimizing the maximum error. Engine requirement for #8677: the knob reader must accept
'fluid'; at'fluid'a gesture plays its measured spring, and at the other characters it plays the character's normalized spring, both from the gesture's velocity; no non-gesture motion switches engines.themeMotion.ts's curve table must let--ease-entranceand--ease-movediffer.Writing rubric results
Scope
Validation
pnpm check:knowledge: alignedgit diff --check: clean