Skip to content

architecture(react-component-runtime): the animator animates a number (INV15) - #8603

Merged
cixzhang merged 5 commits into
mainfrom
spec/internal-animator-value-channel
Oct 27, 2026
Merged

cixzhang merged 5 commits into
mainfrom
spec/internal-animator-value-channel

Conversation

@cixzhang

@cixzhang cixzhang commented Oct 26, 2026 •

Copy link
Copy Markdown
Contributor

Decided (Cindy, 2026-10-26: D34, resolved by convergence: "resolve these with the gesture modules… can they converge?").

Summary

This amends an existing internal module, with no new module and no public API: the animator gains a value mode. It plays a number on the same springs and motion roles and hands it to onUpdate each frame; the component owns the swap threshold, Reduce Motion swaps at once, and it announces nothing in between.

  • First adopters: Stat, Badge count changes, Charts data changes.
  • Status: internal and export-locked (spec:AST-017 FR21).

The record adds INV15 and its verification row.

Writing rubric results

  • R1 present tense: pass. R2 research: none in the record.
  • R3 verification: one row.
  • R4 rejected alternatives: none. R5 change references: none in the record. R6 open questions: none.

@vercel

vercel Bot commented Oct 26, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
astryx Ready Ready Preview Oct 27, 2026 6:09am UTC

Request Review

@astracat-bot

astracat-bot Bot commented Oct 26, 2026 •

Copy link
Copy Markdown

AI review status for this pull request.

Review status Updated
🟢 Reviewed (for maintainers only) Oct 27, 2026, 6:47 AM UTC

@github-actions github-actions Bot added the needs:spec-owner-review Current knowledge records await owner approval label Oct 26, 2026
@github-actions

github-actions Bot commented Oct 26, 2026 •

Copy link
Copy Markdown
Contributor

PR Analysis Report

Previews ready: Storybook and Sandbox were built with this PR's docsite. CI evidence will be added when available.

View Storybook for this PR · View Sandbox for this PR

@meta-cla meta-cla Bot added the CLA Signed This label is managed by the Meta Open Source bot. label Oct 26, 2026
@cixzhang
cixzhang force-pushed the spec/internal-animator-value-channel branch from a0fd3e6 to ef1e4d5 Compare October 26, 2026 23:49
@cixzhang cixzhang changed the title architecture(react-component-runtime): proposed — the animator plays a number (INV15) architecture(react-component-runtime): the animator animates a number (INV15) Oct 26, 2026
@cixzhang

Copy link
Copy Markdown
Contributor Author

/approve-spec ef1e4d5

@github-actions github-actions Bot removed the needs:spec-owner-review Current knowledge records await owner approval label Oct 26, 2026

@astracat-bot astracat-bot Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Requesting changes: INV15’s direction is approved for this head, but its Reduce Motion clause conflicts with the current reduced-motion design record, and two smaller points need fixing. Please address the points below here; a new commit needs a fresh /approve-spec for its head.

  • Reduce Motion: “Under Reduce Motion it swaps at once” skips the opacity-only cross-fade of 200 ms or less that design:reduced-motion DR2 requires under a coarse primary pointer, so restate it as DR1–DR3 (as spec:AST-105 FR4 does) with both pointers in the verification row, or amend DR2 in this pull request.
  • Adopters: component:Badge PR1 and AR1 rule out the timer and live region a Badge adoption needs, so make “the component’s own live region announces the final value” conditional and note that Badge’s record changes first; @astryxdesign/charts cannot reach Core’s internal subpath, so the chart adopter is Lab’s.
  • Routing: add INV15 to the record’s review-applicability triggers (beside INV13 under react-runtime), since architecture:knowledge-contracts INV20 brings a global claim into a component review only through that map.

[Automated review]

Comment on lines +198 to +199
a jump from twelve to over a million does not spin. Under Reduce Motion it
swaps at once. It announces nothing: the component's own live region

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Under a coarse primary pointer, design:reduced-motion DR2 requires an opacity-only cross-fade of 200 ms or less, and its verification fails “a change with no cross-fade”; the animator already does this for its animate calls. Suggested wording, as spec:AST-105 FR4 states it: “Under Reduce Motion it does not count: the new value cross-fades in, opacity only and within 200 ms, under a coarse primary pointer, and appears at once otherwise (design:reduced-motion DR1–DR3).” If counts should snap on touch too, DR2 needs amending in this pull request.

the change size past which it swaps to the new value instead of counting, so
a jump from twelve to over a million does not spin. Under Reduce Motion it
swaps at once. It announces nothing: the component's own live region
announces the final value, never the values between. Number formatting stays

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

component:Badge keeps no live region (AR1: “a changed label is not announced”) and registers no timer or effect (PR1), yet the description names Badge as a first adopter. Suggest making this conditional: “where the component’s own record announces the value, only the final value is announced, never the values between.”

| INV11 | Source boundary check plus hook tests across StrictMode replay and unmount | A second keyboard listener or measurement in Core; a consumer reading a CSS custom property on the root or a shared ancestor for the height; an export of the hook; a component outside Core measuring by a rule other than AST-099 FR2, or riding the keyboard; a listener left after unmount; a Core rider driven by JavaScript per frame or by its own transition; or more than one layout read per keyboard change |
| INV12 | Source boundary check plus real-browser tests on a throttled phone profile over a 10-level by 50-sibling tree and two changes in one frame | A per-frame height or layout, a walk past the area or into a subtree other than `display: contents`, an element moved twice for one frame, an added element, or an exported reporting function fails |
| INV13 | Source boundary check plus bundle analysis of a page with several touch components, and real-browser tests on a throttled phone profile, under a fine pointer, and on a hybrid device | A second copy of a touch module on one page, a component bundling its own copy of a module's primitive, an `import()` of a module in a component, a public export or doc entry for the modules, an install call or installed check in the public API, a touch listener under a fine primary pointer, or an import of `@astryxdesign/core/internal/*` outside Core and Lab fails |
| INV15 | Unit tests of the animator's value mode and real-browser proofs of its adopters | A value off its motion role, a count past the component's swap size, motion under Reduce Motion, an intermediate value announced, or a public export fails |

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

With the Reduce Motion clause restated, this failure signal would read “a count under Reduce Motion, or a change with no cross-fade under a coarse primary pointer”; as written, “motion under Reduce Motion” would also fail the DR2 cross-fade. INV15 also needs a trigger in the review-applicability block at the top of the record (beside INV13 under react-runtime) for adopters’ reviews to load it.

@cixzhang

Copy link
Copy Markdown
Contributor Author

/approve-spec 1ae8907

@astracat-bot astracat-bot Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Requesting changes: INV15’s direction is owner-approved for this head, but its Reduce Motion clause cites design:reduced-motion DR2 for a value written at once on any pointer, while DR2 on main still requires an opacity-only cross-fade of 200 ms or less under a coarse primary pointer and fails “a change with no cross-fade”. That in-place value exception exists only in the open #8645, so land #8645 first, carry its DR2 amendment here, or restate INV15 and its verification row as DR1–DR3 (a cross-fade on a coarse pointer, at once otherwise). A new commit here needs a fresh /approve-spec for its head.

[Automated review]

Comment on lines +200 to +202
a jump from twelve to over a million does not spin. Under reduced motion the
new value is written at once on any pointer, as an in-place value change
(`design:reduced-motion` DR2). It

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

DR2 on main has no in-place value exception: under a coarse primary pointer it requires that “each DR1 transition MUST change opacity only and MUST finish in 200 ms or less”, and its verification fails “a change with no cross-fade”. The exception this cites exists only in #8645. Land that first, or restate as DR1–DR3: “Under reduced motion it does not count: under a coarse primary pointer the new value cross-fades in, opacity only and within 200 ms, and with any other pointer it is written at once.”

| INV11 | Source boundary check plus hook tests across StrictMode replay and unmount | A second keyboard listener or measurement in Core; a consumer reading a CSS custom property on the root or a shared ancestor for the height; an export of the hook; a component outside Core measuring by a rule other than AST-099 FR2, or riding the keyboard; a listener left after unmount; a Core rider driven by JavaScript per frame or by its own transition; or more than one layout read per keyboard change |
| INV12 | Source boundary check plus real-browser tests on a throttled phone profile over a 10-level by 50-sibling tree and two changes in one frame | A per-frame height or layout, a walk past the area or into a subtree other than `display: contents`, an element moved twice for one frame, an added element, or an exported reporting function fails |
| INV13 | Source boundary check plus bundle analysis of a page with several touch components, and real-browser tests on a throttled phone profile, under a fine pointer, and on a hybrid device | A second copy of a touch module on one page, a component bundling its own copy of a module's primitive, an `import()` of a module in a component, a public export or doc entry for the modules, an install call or installed check in the public API, a touch listener under a fine primary pointer, or an import of `@astryxdesign/core/internal/*` outside Core and Lab fails |
| INV15 | Unit tests of the animator's value mode and real-browser proofs of its adopters | A value off its motion role, a count past the component's swap size, a count or cross-fade under reduced motion with a coarse or a fine pointer, an intermediate value announced, or a public export fails |

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Against the current DR2, failing “a … cross-fade under reduced motion with a coarse … pointer” fails exactly what DR2 requires. Restated as DR1–DR3, this would read “a count under reduced motion, or a change with no cross-fade under a coarse primary pointer”.

@cixzhang

Copy link
Copy Markdown
Contributor Author

/approve-spec 1ae8907

@cixzhang

Copy link
Copy Markdown
Contributor Author

/approve-spec 61c65cd

@astracat-bot astracat-bot Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Recommending approval: the animator's value mode (INV15) is owner-approved for this head, and its reduced-motion, announcement and internal-only clauses match the current reduced-motion, status-announcement and release-compatibility specs. The reduced-motion conflict flagged on earlier heads is resolved now that DR2's in-place value exception is on main. For the adopting pull requests: Badge's own record (PR1, AR1) rules out the timer or effect a count needs and keeps no live region, so a Badge adoption starts with that record, and only Lab's Chart, not the separate charts package, can reach Core's internal animator.

[Automated review]

@cixzhang
cixzhang merged commit f881aff into main Oct 27, 2026
67 checks passed
@github-actions
github-actions Bot deleted the spec/internal-animator-value-channel branch October 28, 2026 06:17

This branch was successfully deployed

1 active deployment
Preview — 61c65cdb Deployed Oct 27, 2026 by vercel[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

CLA Signed This label is managed by the Meta Open Source bot.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant