Repository navigation
fix(motion): a carried pending animation runs in step with its original - #10983
Conversation
A transient copy carries its element's animations by start time. One saved while its play was still pending had no start time yet, so the copy took only its current time and started on a frame of its own. On a loaded machine, the SideNav rail's leaving copy started the toggle's press fade 333 ms after the toggle's. The copy now takes the start its original resolves to, at once or once the original's play starts. Both callers get it: the transient copy and the layer runtime's re-placement. The rail's reduced-motion press proof read the copy's start only in frame callbacks, which on a busy page ran after the copy was gone. It also reads the start as the fade turns ready, and it keeps a frame trace. A copy fade that never started fails as frame starvation only when the trace shows no frame while the copy held it; otherwise it fails plainly.
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
AI review status for this pull request.
|
PR Analysis Report🔎 Preview ·
|
| Component | Size | LoC | Visual · A11y · RTL |
|---|---|---|---|
| InfoTip | 47.0 kB (+76 B) · 5.3 kB CSS (0) | — | — · — · — |
| DateTimeInput | 209.1 kB (+69 B) · 18.7 kB CSS (0) | — | — · — · — |
| Tokenizer | 91.9 kB (+69 B) · 18.8 kB CSS (0) | — | — · — · — |
112 more components
| Component | Size | LoC | Visual · A11y · RTL |
|---|---|---|---|
| NumberInput | 72.2 kB (+66 B) · 11.4 kB CSS (0) | — | — · — · — |
| Toast | 98.5 kB (+66 B) · 10.3 kB CSS (0) | — | — · — · — |
| Avatar | 43.7 kB (+64 B) · 5.6 kB CSS (0) | — | — · — · — |
| TopNavMenu | 75.0 kB (+62 B) · 11.2 kB CSS (0) | — | — · — · — |
| AvatarGroup | 46.4 kB (+61 B) · 5.7 kB CSS (0) | — | — · — · — |
| CodeBlock | 75.8 kB (+61 B) · 11.3 kB CSS (0) | — | — · — · — |
| Stepper | 62.3 kB (+61 B) · 10.1 kB CSS (0) | — | — · — · — |
| TopNavHeading | 75.6 kB (+61 B) · 11.2 kB CSS (0) | — | — · — · — |
| TabList | 44.3 kB (+60 B) · 6.5 kB CSS (0) | — | — · — · — |
| ContextMenu | 109.3 kB (+59 B) · 17.4 kB CSS (0) | — | — · — · — |
| SideNav | 114.9 kB (+59 B) · 11.4 kB CSS (0) | — | ✓ · ✓ · ✓ |
| SideNavHeading | 76.0 kB (+59 B) · 11.3 kB CSS (0) | — | ✓ · ✓ · ✓ |
| Thumbnail | 65.0 kB (+59 B) · 11.6 kB CSS (0) | — | — · — · — |
| AppShell | 91.8 kB (+58 B) · 13.5 kB CSS (0) | — | — · — · — |
| Popover | 91.3 kB (+58 B) · 14.2 kB CSS (0) | — | — · — · — |
| Slider | 109.6 kB (+58 B) · 8.8 kB CSS (0) | — | — · — · — |
| Toolbar | 44.3 kB (+58 B) · 8.1 kB CSS (0) | — | — · — · — |
| DrawerHeader | 63.7 kB (+57 B) · 12.9 kB CSS (0) | — | — · — · — |
| Link | 53.5 kB (+57 B) · 7.0 kB CSS (0) | — | — · — · — |
| MultiSelector | 95.4 kB (+57 B) · 16.8 kB CSS (0) | — | — · — · — |
| Tooltip | 29.9 kB (+57 B) · 4.4 kB CSS (0) | — | — · — · — |
| Button | 60.7 kB (+56 B) · 10.0 kB CSS (0) | — | — · — · — |
| DialogHeader | 63.5 kB (+56 B) · 11.5 kB CSS (0) | — | — · — · — |
| FileInput | 69.6 kB (+56 B) · 10.9 kB CSS (0) | — | — · — · — |
| PowerSearch | 289.1 kB (+56 B) · 24.2 kB CSS (0) | — | — · — · — |
| Selector | 100.7 kB (+56 B) · 17.4 kB CSS (0) | — | — · — · — |
| SideNavCollapseButton | 61.5 kB (+56 B) · 10.0 kB CSS (0) | — | ✓ · ✓ · ✓ |
| ChatLayoutScrollButton | 61.2 kB (+55 B) · 10.2 kB CSS (0) | — | — · — · — |
| ComplexSelector | 71.4 kB (+55 B) · 11.8 kB CSS (0) | — | — · — · — |
| DateInput | 187.4 kB (+55 B) · 17.0 kB CSS (0) | — | — · — · — |
| SegmentedControl | 96.6 kB (+55 B) · 6.9 kB CSS (0) | — | — · — · — |
| TableCell | 110.5 kB (+55 B) · 17.9 kB CSS (0) | — | — · — · — |
| TableHeaderCell | 110.1 kB (+55 B) · 17.7 kB CSS (0) | — | — · — · — |
| ToggleButton | 87.1 kB (+55 B) · 10.1 kB CSS (0) | — | — · — · — |
| Calendar | 71.7 kB (+54 B) · 10.6 kB CSS (0) | — | — · — · — |
| ChatLayout | 83.3 kB (+54 B) · 10.5 kB CSS (0) | — | — · — · — |
| Pagination | 110.7 kB (+54 B) · 17.8 kB CSS (0) | — | — · — · — |
| StatusDot | 31.6 kB (+54 B) · 5.3 kB CSS (0) | — | — · — · — |
| TextInput | 68.2 kB (+54 B) · 11.2 kB CSS (0) | — | — · — · — |
| TopNav | 72.6 kB (+54 B) · 10.9 kB CSS (0) | — | — · — · — |
| Banner | 62.6 kB (+53 B) · 10.5 kB CSS (0) | — | — · — · — |
| ChatSendButton | 61.1 kB (+53 B) · 10.0 kB CSS (0) | — | — · — · — |
| Lightbox | 122.9 kB (+53 B) · 10.6 kB CSS (0) | — | — · — · — |
| RadioList | 56.8 kB (+53 B) · 7.3 kB CSS (0) | — | — · — · — |
| RadioListItem | 67.9 kB (+53 B) · 10.1 kB CSS (0) | — | — · — · — |
| TabMenu | 72.2 kB (+53 B) · 11.1 kB CSS (0) | — | — · — · — |
| ChatDictationButton | 61.2 kB (+52 B) · 10.0 kB CSS (0) | — | — · — · — |
| DropdownMenu | 97.5 kB (+52 B) · 17.6 kB CSS (0) | — | — · — · — |
| Field | 55.4 kB (+52 B) · 7.2 kB CSS (0) | — | — · — · — |
| IconButton | 60.7 kB (+52 B) · 10.0 kB CSS (0) | — | — · — · — |
| Markdown | 188.7 kB (+52 B) · 20.6 kB CSS (0) | — | — · — · — |
| MobileNav | 71.0 kB (+52 B) · 10.6 kB CSS (0) | — | — · — · — |
| MobileNavToggle | 61.0 kB (+52 B) · 10.0 kB CSS (0) | — | — · — · — |
| MoreMenu | 97.8 kB (+52 B) · 17.6 kB CSS (0) | — | — · — · — |
| ChatComposer | 78.8 kB (+51 B) · 12.0 kB CSS (0) | — | — · — · — |
| InputGroup | 57.1 kB (+51 B) · 7.8 kB CSS (0) | — | — · — · — |
| TimeInput | 162.8 kB (+51 B) · 16.0 kB CSS (0) | — | — · — · — |
| Typeahead | 80.1 kB (+51 B) · 12.4 kB CSS (0) | — | — · — · — |
| BreadcrumbItem | 85.0 kB (+50 B) · 12.1 kB CSS (0) | — | — · — · — |
| FieldLabel | 51.5 kB (+50 B) · 5.7 kB CSS (0) | — | — · — · — |
| HoverCard | 28.2 kB (+49 B) · 4.4 kB CSS (0) | — | — · — · — |
| CheckboxInput | 64.8 kB (+48 B) · 9.2 kB CSS (0) | — | — · — · — |
| Table | 126.0 kB (+48 B) · 18.3 kB CSS (0) | — | — · — · — |
| TableSelectionToolbar | 70.9 kB (+48 B) · 13.2 kB CSS (0) | — | — · — · — |
| TextArea | 62.8 kB (+48 B) · 9.3 kB CSS (0) | — | — · — · — |
| Carousel | 70.3 kB (+47 B) · 10.9 kB CSS (0) | — | — · — · — |
| CheckboxListItem | 71.7 kB (+47 B) · 11.4 kB CSS (0) | — | — · — · — |
| AlertDialog | 105.8 kB (+46 B) · 14.6 kB CSS (0) | — | — · — · — |
| AvatarGroupOverflow | 49.4 kB (+46 B) · 5.7 kB CSS (0) | — | — · — · — |
| BaseTypeahead | 71.5 kB (+46 B) · 10.9 kB CSS (0) | — | — · — · — |
| ListItem | 70.8 kB (+46 B) · 11.4 kB CSS (0) | — | — · — · — |
| CheckboxList | 68.9 kB (+45 B) · 7.7 kB CSS (0) | — | — · — · — |
| DateRangeInput | 93.3 kB (+45 B) · 12.5 kB CSS (0) | — | — · — · — |
| TopNavMegaMenu | 70.1 kB (+45 B) · 11.8 kB CSS (0) | — | — · — · — |
| ChatComposerInput | 76.5 kB (+44 B) · 11.3 kB CSS (0) | — | — · — · — |
| ChatComposerTokenElement | 76.5 kB (+44 B) · 11.3 kB CSS (0) | — | — · — · — |
| DropdownMenuSubMenu | 70.6 kB (+43 B) · 9.7 kB CSS (0) | — | — · — · — |
| Switch | 104.2 kB (+43 B) · 9.9 kB CSS (0) | — | — · — · — |
| SideNavItem | 70.9 kB (+42 B) · 11.1 kB CSS (0) | — | ✓ · ✓ · ✓ |
| ChatMessageList | 29.4 kB (0) · 7.0 kB CSS (0) | — | — · — · — |
| ChatToolCalls | 33.3 kB (0) · 8.3 kB CSS (0) | — | — · — · — |
| CommandPalette | 73.5 kB (0) · 12.7 kB CSS (0) | — | — · — · — |
| CommandPaletteInput | 33.0 kB (0) · 7.5 kB CSS (0) | — | — · — · — |
| Heading | 13.7 kB (0) · 5.4 kB CSS (0) | — | — · — · — |
| ProgressBar | 11.7 kB (0) · 6.3 kB CSS (0) | — | — · — · — |
| SideNavSection | 6.9 kB (0) · 3.7 kB CSS (0) | — | ✓ · ✓ · ✓ |
| Timer | 15.3 kB (0) · 6.0 kB CSS (0) | — | — · — · — |
| Timestamp | 34.3 kB (0) · 10.2 kB CSS (0) | — | — · — · — |
| Spinner | 26.0 kB (−1 B) · 6.2 kB CSS (0) | — | — · — · — |
| Text | 13.2 kB (−1 B) · 5.4 kB CSS (0) | — | — · — · — |
| charts/Chart | 205.0 kB (new) · 494 B CSS (new) | — | — · — · — |
| charts/ChartLegend | 53.0 kB (new) · 224 B CSS (new) | — | — · — · — |
| charts/ChartTooltip | 182.3 kB (new) · 423 B CSS (new) | — | — · — · — |
| lab/ChatEmojiPicker | 106.5 kB (new) · 773 B CSS (new) | — | — · — · — |
| lab/ChatReactionBar | 107.6 kB (new) · 1.1 kB CSS (new) | — | — · — · — |
| lab/CommentComposer | 152.6 kB (new) · 1.9 kB CSS (new) | — | — · — · — |
| lab/CommentPin | 57.6 kB (new) · 1.2 kB CSS (new) | — | — · — · — |
| lab/Comments | 352.6 kB (new) · 2.5 kB CSS (new) | — | — · — · — |
| lab/CommentThread | 345.7 kB (new) · 2.4 kB CSS (new) | — | — · — · — |
| lab/DialogHeroHeader | 83.7 kB (new) · 372 B CSS (new) | — | — · — · — |
| lab/DiffViewer | 87.8 kB (new) · 2.1 kB CSS (new) | — | — · — · — |
| lab/EmojiPicker | 87.4 kB (new) · 751 B CSS (new) | — | — · — · — |
| lab/LineClamp | 15.3 kB (new) · 168 B CSS (new) | — | — · — · — |
| lab/ListInput | 88.7 kB (new) · 922 B CSS (new) | — | — · — · — |
| lab/Schedule | 106.6 kB (new) · 3.9 kB CSS (new) | — | — · — · — |
| lab/SelectableCardGroup | 64.9 kB (new) · 162 B CSS (new) | — | — · — · — |
| lab/TourStep | 97.6 kB (new) · 590 B CSS (new) | — | — · — · — |
| lab/TransferList | 102.6 kB (new) · 1.2 kB CSS (new) | — | — · — · — |
| lab/TransferListSelector | 110.1 kB (new) · 1.4 kB CSS (new) | — | — · — · — |
| richtext/RichTextEditor | 298.6 kB (new) · 2.6 kB CSS (new) | — | — · — · — |
| richtext/RichTextEditorToolbar | 279.1 kB (new) · 454 B CSS (new) | — | — · — · — |
| richtext/RichTextView | 276.8 kB (new) · 2.3 kB CSS (new) | — | — · — · — |
Package size: measured; main has no measurement of the merge base to compare yet.
API changes: none in this pull request
Committed API report behind this build: cli 29 rows, core 36 rows; run pnpm api:report.
Touched components checked; add ci:run-visual, ci:run-a11y or ci:run-rtl to run the full suites.
Generated by PR Enrichment workflow | View full report
|
/approve-spec dc59ea5 |
There was a problem hiding this comment.
Approved pending CI: CI has not run on this head yet. The pull request is a draft from a fork, so once it is ready for review, a maintainer adds the ci:run label so CI runs.
The fix holds up: the copy now takes its original's start, and the changed press proof fails on main under a slowed CPU (the copy's fade started about 420 ms late) but never fails that way on this head.
- Optional: the first sentence of
followStart's doc comment (packages/core/src/motion/carryAnimations.ts:172) restates the code below it. Keeping only the pending-start quirk would match the repository's comment guidance.
[Automated review]
| * Gives `next` the start time `original` runs on, now or, while its play is | ||
| * still pending, once that play starts. A pending play has no start time | ||
| * yet: it resolves on the frame that first draws the animation. |
There was a problem hiding this comment.
Optional: the first sentence restates the two branches below. Keeping only the quirk is enough, for example: "A pending play has no start time. Its start resolves on the frame that first draws the animation." The comment in restore() can then keep only its reason, that the two run in step.
There was a problem hiding this comment.
Kept for this head, which the spec owner has stamped. The trim to the pending-start quirk goes in the next change to this file.
User impact
On a busy page, a transient copy can start a carried animation after its original. The SideNav rail's leaving copy started the toggle's press fade 333 ms late.
Problem and solution fit
The copy now takes the start its original resolves to.
Expected behavior and authority
carryAnimations.tscarries a running animation by its start time. A pending one now follows the same rule.Smallest restoration
carryAnimations.ts: a running animation saved while its play was pending takes its original's start time, now or once that play starts.motion/transientCopy.ts) and the layer runtime's re-placement (Layer/preserveAnimations.ts).Evidence
preserveAnimations) passes at one worker in Chromium and WebKit. So do layerExitCopy, LayerCloseLayout, PopoverTouchMotion and the other SideNav proofs.Scope
Testing
This head, dc59ea5:
pnpm -F @astryxdesign/core typecheck,pnpm check:knowledgeandpnpm check:changesetspass. ESLint and Prettier pass on the changed files.