Skip to content

fix(core): a press's release fades on the theme's exit motion tokens - #9890

Merged
cixzhang merged 1 commit into
mainfrom
fix/press-release-exit-tokens
Nov 4, 2026
Merged

cixzhang merged 1 commit into
mainfrom
fix/press-release-exit-tokens

Conversation

@cixzhang

@cixzhang cixzhang commented Nov 4, 2026 •

Copy link
Copy Markdown
Contributor

User impact

This affects people who press a control on a phone or tablet: buttons, cards, switches, checkboxes, list and tree rows, tabs, navigation items and action groups, every surface that shows the shared pressed colour.

  • Today: after the lift, the pressed colour fades over 200 ms, scaled by the theme's tempo, on a curve of its own. Most of the colour is gone in about 40 ms, so the fade is hard to see. The theme's duration and easing tokens do not reach it.
  • After this change: the release fades on the theme's exit motion tokens, --duration-exit and --ease-exit. With the default theme that is 175 ms on an accelerating curve. The colour stays a little longer, then goes. A theme that changes those tokens, or its tempo, changes the release too.
  • Unchanged: the press still shows at once. A mouse press on a desktop is unchanged. Under Reduce Motion, a finger's release still fades for no more than 200 ms. A theme's tempo still scales the release, now through --duration-exit.

The owner's words, and the code for each

The owner decided (2026-11-03): "my expectation with these kinds of press fade motion is we're using the appropriate motion tokens to do the job however that timing is supposed to be". Specs & Decisions recorded the tokens as --duration-exit and --ease-exit, on every pointer, for every release that fades today, and no new fades.

The decision The code
The release fades on --duration-exit utils/interactionOverlay.stylex.ts: PRESS_RELEASE_DURATION = durationVars['--duration-exit']. The same token in privateAttributes/press.stylex.ts (list row layer) and Switch/Switch.tsx (Switch's press layers).
… with --ease-exit RELEASE_EASE = easeVars['--ease-exit'] in the same three files.
The controller's clock agrees with the fade utils/pressFeedback.ts: pressFadeMs reads the computed --duration-exit on the pressed element. Without a readable value it uses the token's default (PRESS_FADE_MS, 175 ms). Action groups (hooks/actionGroupTracker.ts) read the same function.
Reduce Motion keeps DR2's bound min(var(--duration-exit), 200ms) in the stylesheet, and the same bound in the controller. The 200 ms is the shared Reduce Motion fade, reducedMotionFadeConsts.duration.
No new fades The fine-pointer overlay (:active) is unchanged, so a desktop mouse press is as on main.
// utils/interactionOverlay.stylex.ts
const PRESS_RELEASE_DURATION = durationVars['--duration-exit'];
const PRESS_RELEASE_DURATION_REDUCED = `min(${durationVars['--duration-exit']}, ${reducedMotionFadeConsts.duration})`;
const RELEASE_EASE = easeVars['--ease-exit'];

What changes, by component

Every release that fades: a finger, mouse, pen or key press on a phone or tablet, and a pen press on a desktop (the press controller paints it there). With the default theme the release goes from 200 ms on cubic-bezier(0, 0, 0.2, 1) to 175 ms on cubic-bezier(0.3, 0, 0.6, 0.6).

Surface Release before Release after
Every component that composes the shared press overlay: AvatarGroup, Button, Calendar, CheckboxInput, ClickableCard, Collapsible, CommandPalette, ComplexSelector, DateInput, Item, Link, MultiSelector, NumberInput, Outline, SegmentedControl, SelectableCard, Selector, SideNav, Stepper, Switch, TabList, Thumbnail, Token, TopNav, TreeList 200 ms, own curve --duration-exit, --ease-exit
List and TreeList rows (the compositor layer) 200 ms, own curve --duration-exit, --ease-exit
Switch (track and thumb press layers) 200 ms, own curve --duration-exit, --ease-exit
Action groups: AlertDialog actions, SegmentedControl 200 ms × tempo --duration-exit
A desktop pen press (the press controller) 200 ms, own curve --duration-exit, --ease-exit
A desktop mouse press (:active) as on main as on main (unchanged)

Components that animate their own desktop press in CSS are out of scope here. ClickableCard, SelectableCard and Thumbnail move in their own pull request, and the rest follow in the next one.

Records

  • spec:AST-094 FR5: "A press shows at once. Every press release that fades does so on the theme's exit motion tokens (--duration-exit, --ease-exit), on every device and pointer, by the owner's decision (2026-11-03); under Reduce Motion, design:reduced-motion DR2 applies."
  • component:List FR11 and component:Button FR15: the release fades on the theme's exit motion tokens (--duration-exit, --ease-exit).
  • spec:AST-108: Button FR15's release follows tempo through --duration-exit, which references a tempo-scaled duration.
  • timing.press.highlightOutMs and highlightOutCurve stay in the motion table, marked "reference only, not played".
  • pressConsts.releaseMs, exported from @astryxdesign/core/utils/interactionOverlay.stylex, stays exported with its value, documented as the measured reference value; press releases now play --duration-exit.

Writing rubric results

R1 narration: FR5's new sentence said "today … still"; the clause is removed, because FR11 and DEC-21 already say which presses fade.
R2 research: none in the records; the fade comparison is in a linked explainer.
R3 evidence: none changed.
R4 rejected alternatives: none added.
R5 change references: none.
R6 open questions: none added.

Compatibility

A press's release timing changes on every touch-first device, for a pen press on a desktop, and with any theme that sets --duration-exit or --ease-exit. Every press release that fades does so on the theme's exit motion tokens, on every device, by the owner's decision (2026-11-03). A mouse press on a desktop is unchanged: its pixels match main. No API change: pressConsts.releaseMs stays exported as a reference value.

Verification

  • Red first: 18 new or changed unit cases fail with the old stylesheet and controller, and pass here. They cover:

    • the controller follows a theme's --duration-exit, in ms and in s;
    • the 200 ms bound under Reduce Motion;
    • a mouse press on a phone;
    • action groups;
    • the overlay, row layer and Switch arms declaring var(--duration-exit), min(var(--duration-exit), 200ms) and var(--ease-exit).
  • Suites: the press, overlay, Switch, List, Item, TreeList, action-group and motion-table unit suites pass (2,091 tests), and so does the shipped stylesheet test (scripts/build-css.test.mjs, 14 of 14). Lint (strict) on the changed files and the core type check are clean. check:knowledge passes. review:pre reports no findings.

  • Since the phone check at 9864140: no behaviour change. The Reduce Motion bound now reads the shared reducedMotionFadeConsts.duration (the same 200 ms), pressConsts.releaseMs is kept as a reference value, the default clock uses the shared resolveTokenReferences, the controller parses the token with the shared parseMotionRoleValue('duration', …), the stylesheet test reads the new clocks, and the changeset, commit message and FR5 wording are corrected.

  • Real Chromium (phone viewport): the ButtonPress, ListRowPress, ListRowPressPaths and Switch interaction specs pass: 66 passed, 1 skipped (a WebKit-only case). The specs now read the release clock and curve from the page's --duration-exit and --ease-exit. Three of them fail against main's Storybook: the row's release curve, the button's release clock, and Switch following a theme's --duration-exit with the 200 ms Reduce Motion bound.

  • Phone, before and after (real Chromium, release seeked frame by frame; pressed-colour strength):

    Time after the lift 0 ms 33 ms 50 ms 67 ms 100 ms 133 ms
    main: 200 ms, old curve (row and button) 1 0.56 0.42 0.31 0.16 0.07
    here: exit tokens (row and button) 1 0.87 0.73 0.56 0.22 0

    The Storybook theme sets --duration-fast, which --duration-exit uses, to 125 ms, so the release there is 125 ms. With core's default tokens it is 175 ms.

  • Desktop, before and after: a mouse hover, held press and release on a List row and a Button: 0 different pixels against main in all six frames.

Card 39 pass carry-over

Cindy passed card 39 at 9864140. Since then the head took review fixes with no behaviour change (the controller now parses the token with the shared parseMotionRoleValue), and it is now rebased onto main after #9758, #9762 and #9765 merged. The range-diff of this pull request's own change, from d92c7ef to this head, is two changeset lines: this changeset credits its author, and the list-row changeset no longer says the row's release keeps "the same clock and curve" (this pull request changes them).

Real Chromium, phone touch emulation, the same row ("Sent") and Button, the release seeked to the same frames. The values are pressed-colour strength, the same for the row and the Button. Each side is built from its exact head's source with the same Storybook stories.

Frame after the lift 0 ms 25 ms 50 ms 100 ms 150 ms Release
9864140 (passed), Reduce Motion off and on 1 0.921 0.725 0.222 0 125 ms
this head, Reduce Motion off and on 1 0.921 0.725 0.222 0 125 ms

Every frame matches. Desktop mouse at this head against main (with #9765): 0 different pixels in hover, held press, and the frame after the release, for the row and the Button, in four runs.

Desktop pen press (fine pointer; the press controller paints it), main against this head:

Frame after the lift 0 ms 25 ms 50 ms 100 ms 150 ms Release
main 1 0.641 0.422 0.161 0.036 200 ms
this head 1 0.921 0.725 0.222 0 125 ms

The pen's release is an existing fade, retimed onto the exit tokens by FR5's every-device, every-pointer decision.

Scope

  • One solution: every press release that fades plays the exit motion tokens.
  • No new fade, no API change.
  • Public text and artifacts contain no internal context.

@vercel

vercel Bot commented Nov 4, 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 Nov 4, 2026 8:06pm UTC

Request Review

@meta-cla meta-cla Bot added the CLA Signed This label is managed by the Meta Open Source bot. label Nov 4, 2026
@astracat-bot

astracat-bot Bot commented Nov 4, 2026 •

Copy link
Copy Markdown

AI review status for this pull request.

Review status Updated
🟢 Reviewed (for maintainers only) Nov 4, 2026, 8:28 PM UTC

@cixzhang

cixzhang commented Nov 4, 2026

Copy link
Copy Markdown
Contributor Author

/approve-spec 9864140

@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: moving the press release onto the theme's exit motion tokens has owner-approved spec direction for this head, but four things need fixing first.

  • pressConsts.releaseMs, exported from @astryxdesign/core/utils/interactionOverlay.stylex since 0.7.6, is renamed to reducedMotionReleaseMs in a patch with no compatibility alias or migration, so keep the released member and take the Reduce Motion bound from the existing internal reducedMotionFadeConsts.duration (or ship the rename as [breaking] with a migration).
  • scripts/build-css.test.mjs still reads releaseMs: and the deleted utils/rowPressLayer.stylex.ts, so 2 of its 14 tests fail on this head while all pass on the base; these are the two source-build failures the description puts down to a missing install.
  • The Changeset and the new spec:AST-094 FR5 sentence say a mouse or pen press on a desktop releases at once, but a pen press on a fine-pointer device is painted by the press controller and fades (now on the exit tokens), the mouse wording contradicts FR11 and DEC-21, and the release already followed tempo before this change, so those sentences need correcting.
  • defaultTokenMs in utils/pressGesture.ts re-implements the var() resolution that resolveTokenReferences already provides, and reducedMotionReleaseMs restates reducedMotionFadeConsts.duration, so call the shared ones instead.

The rest of the change, the stylesheet arms and the controller reading --duration-exit, looks right, and the unit suites pass.

[Automated review]

* The longest a finger's release may fade under Reduce Motion, in ms: the
* Reduce Motion cross-fade's bound (`timing.reducedMotionCrossFade`).
*/
reducedMotionReleaseMs: 200,

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

pressConsts is public on @astryxdesign/core/utils/interactionOverlay.stylex (api-report.md lists const pressConsts: { releaseMs: number }, shipped since 0.7.6), so renaming releaseMs here breaks a consumer that reads it, in a patch release. Keep releaseMs as released and take the Reduce Motion bound from the internal reducedMotionFadeConsts.duration (motion/reducedMotion.stylex.ts) in the stylesheets and timing.reducedMotionCrossFadeMs in the controller, or ship the rename as [breaking] with a migration.

@@ -1,27 +0,0 @@
// Copyright (c) Meta Platforms, Inc. and affiliates.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

scripts/build-css.test.mjs still opens this file (readLayerConsts) and looks for releaseMs: in interactionOverlay.stylex.ts (readReleaseMs), so 2 of its 14 tests fail on this head and pass on the base. Point both at the token declarations (var(--duration-exit), min(var(--duration-exit),.2s), var(--ease-exit)), as interactionOverlay.cell.test.ts now does.

Comment thread .changeset/press-release-exit-tokens.md Outdated
'@astryxdesign/core': patch
---

[fix] A press's release now fades on the theme's exit motion tokens, `--duration-exit` and `--ease-exit`, instead of a fixed 200 ms on a curve of its own. This covers every release that fades today: a finger's press, and a mouse, pen or key press on a phone or tablet, on buttons, cards, switches, checkboxes, list and tree rows, menu items and action groups. With the default theme the release is 175 ms and holds its colour a little longer before it goes. A theme that changes `--duration-exit`, `--ease-exit` or its `tempo` now changes the release too. Under Reduce Motion a finger's release still fades for no more than 200 ms. A mouse or pen press on a desktop still releases at once, as before.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

On a fine-pointer device the press controller paints a pen press and its release fades (200 ms on cubic-bezier(0, 0, 0.2, 1) before, the exit tokens now), so 'A mouse or pen press on a desktop still releases at once' is wrong for a pen. 'or its tempo now changes the release too' also describes what 0.7.7 already did. Suggested: 'A mouse press on a desktop still releases at once; a pen's release there fades on the same tokens.' and 'A theme that changes --duration-exit or --ease-exit now changes the release; tempo still does.'

Comment on lines +205 to +206
decision (2026-11-03); a press that has no release fade (a mouse or pen on
a fine-pointer device, on the press overlay) releases at once.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

A pen on a fine-pointer device does have a release fade: the controller paints every press but a mouse's, and the overlay's fading arm is not gated to pointer: coarse. For a mouse, this sentence contradicts FR11's fine-pointer profile ('through the same press controller and release fade as a finger's, in place of CSS :active') and DEC-21, which stay as they are. Drop 'or pen', and reconcile the mouse case with FR11 and DEC-21.

Comment thread packages/core/src/utils/pressGesture.ts Outdated
Comment on lines +79 to +85
function defaultTokenMs(token: keyof typeof durationDefaults): number {
const value: string = durationDefaults[token];
const reference = /^var\((--[\w-]+)\)$/u.exec(value);
return reference == null
? Number.parseFloat(value)
: defaultTokenMs(reference[1] as keyof typeof durationDefaults);
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

This re-implements the var() chase that resolveTokenReferences (theme/tokenReferences.ts) already does over this token map (themeMotion.ts uses it), without its fallback and cycle handling. export const PRESS_FADE_MS = Number.parseFloat(resolveTokenReferences(durationDefaults)['--duration-exit']); keeps one path.

Comment on lines +152 to +153
* The release's curve: the theme's exit easing. The list row's layer (privateAttributes/press.stylex.ts) and Switch's press layers
* use the same token; interactionOverlay.cell.test.ts fails if they differ.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Non-blocking: interactionOverlay.cell.test.ts never renders Switch; Switch.test.tsx holds Switch's curve to this one. Suggested: 'The list row's layer and Switch's press layers use the same token. interactionOverlay.cell.test.ts and Switch.test.tsx hold them to it.'

@cixzhang
cixzhang force-pushed the fix/press-release-exit-tokens branch 2 times, most recently from 2aa1f8b to 3df0724 Compare November 4, 2026 07:54
@cixzhang

cixzhang commented Nov 4, 2026

Copy link
Copy Markdown
Contributor Author

/approve-spec 3df0724

@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: moving every press release onto the theme's exit motion tokens has owner-approved spec direction for this head, pressConsts.releaseMs keeps its released shape and scripts/build-css.test.mjs passes, but two things remain.

  • Miss: durationMs in utils/pressFeedback.ts re-implements the CSS time parsing that parseMotionRoleValue('duration', …) in motion/roles.ts already provides (SegmentedControl reads theme durations with it), so call the shared parser for both --duration-exit and reducedMotionFadeConsts.duration and delete the copy.
  • The description's User impact says today's release is "a fixed 200 ms" that "a theme's motion settings do not reach" (the Changeset also says "a fixed 200 ms"), but on the base a theme's tempo already scales it, as the description's own Unchanged bullet says, and the commit message says a desktop pen press releases at once while it fades, so reword them, for example "Today: the pressed colour fades over 200 ms, scaled by the theme's tempo, on a curve of its own; the theme's duration and easing tokens do not reach it."

Smaller and non-blocking: the now-unused timing import in interactionOverlay.cell.test.ts can go, and the comment above RELEASE_EASE should name Switch.test.tsx as the test that holds Switch's curve.

[Automated review]

Comment on lines 177 to 185
/** A CSS time in ms (`'175ms'` → 175, `'0.2s'` → 200); NaN for anything else. */
function durationMs(value: string): number {
const match = /^(-?[\d.]+)(ms|s)$/u.exec(value.trim());
if (match == null) {
return Number.NaN;
}
const amount = Number(match[1]);
return match[2] === 's' ? amount * 1000 : amount;
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Miss: this re-implements parseMotionRoleValue('duration', …) from motion/roles.ts, which SegmentedControl already uses to read a theme duration off computed style, and it already differs (it rejects an exponent the shared parser takes). Suggested:

const exit =
  parseMotionRoleValue('duration', getComputedStyle(element).getPropertyValue('--duration-exit')) ??
  PRESS_FADE_MS;

and the same call for reducedMotionFadeConsts.duration, then delete durationMs.

Comment on lines +145 to +146
* The release's curve: the theme's exit easing. The list row's layer (privateAttributes/press.stylex.ts) and Switch's press layers
* use the same token; interactionOverlay.cell.test.ts fails if they differ.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Non-blocking: interactionOverlay.cell.test.ts never renders Switch; Switch.test.tsx holds Switch's curve. Suggested: "The list row's layer and Switch's press layers use the same token. interactionOverlay.cell.test.ts and Switch.test.tsx hold them to it."

@cixzhang
cixzhang force-pushed the fix/press-release-exit-tokens branch from 3df0724 to d92c7ef Compare November 4, 2026 09:02
@cixzhang

cixzhang commented Nov 4, 2026

Copy link
Copy Markdown
Contributor Author

/approve-spec d92c7ef

@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.

Approved pending CI: moving every press release onto the theme's exit motion tokens has owner-approved spec direction for this head, and both earlier blocking points are fixed (the controller now uses the shared parseMotionRoleValue, and the description, Changeset and commit message describe today's release correctly). Build and test CI has not run on this head yet.

Non-blocking, for this or a follow-up:

  • The headers of utils/interactionOverlay.stylex.ts and privateAttributes/press.stylex.ts still name the deleted utils/rowPressLayer.stylex.ts and the old clocks, and PressTracker's releaseMs comment still promises a 200 ms fade.
  • spec:AST-094 FR5 now says every press release fades on the exit tokens on every pointer, while a mouse release on ClickableCard, SelectableCard and Thumbnail still uses --duration-fast and --ease-standard; an Implementation gap: line would keep the record accurate until those follow.

[Automated review]

Comment on lines +201 to +204
A press shows at once. Every press release that fades does so on the
theme's exit motion tokens (`--duration-exit`, `--ease-exit`), on every
device and pointer, by the owner's decision (2026-11-03); under Reduce
Motion, `design:reduced-motion` DR2 applies.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Non-blocking: this says every press release fades on the exit tokens on every device and pointer, but a mouse release on ClickableCard, SelectableCard and Thumbnail still transitions on --duration-fast and --ease-standard (for example ClickableCard.tsx lines 124-130). Until those follow, an Implementation gap: line here would keep the record accurate.

@cixzhang
cixzhang force-pushed the fix/press-touch-down-highlight branch from 1b6a265 to 3b74202 Compare November 4, 2026 14:51
Every press release that fades now plays `--duration-exit` and
`--ease-exit` instead of 200 ms, scaled by the theme's tempo, on a curve
of its own: the shared overlay's touch release, the controller's release
clock (which action groups read too), Switch's press layers and the list
row layer. A desktop pen press, which the controller fades, moves to the
tokens too. Under Reduce Motion a finger's release is no longer than
200 ms, as before. A mouse press on a desktop is unchanged.
@cixzhang
cixzhang force-pushed the fix/press-release-exit-tokens branch from d92c7ef to 82dd709 Compare November 4, 2026 19:59
@cixzhang
cixzhang changed the base branch from fix/press-touch-down-highlight to main November 4, 2026 19:59
@cixzhang

cixzhang commented Nov 4, 2026

Copy link
Copy Markdown
Contributor Author

/approve-spec 82dd709

@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.

Approved pending CI: build and test CI is still running on this head. Moving every press release that fades onto --duration-exit and --ease-exit has owner-approved spec direction for this head, and the stylesheet arms, the controller's clock and the action groups all read that one token. In Chromium the touch row and Button release now runs 175 ms on the exit curve, holding 0.74 of its colour at 67 ms instead of 0.31.

Non-blocking, for this or a follow-up:

  • The headers of utils/interactionOverlay.stylex.ts and privateAttributes/press.stylex.ts still name the deleted utils/rowPressLayer.stylex.ts and the old clocks. gestures/PressTracker.ts still says every surface releases on the 200 ms deselect clock.
  • spec:AST-094 FR5 now says every release that fades plays the exit tokens on every pointer. ClickableCard, SelectableCard and Thumbnail still release a desktop mouse press on --duration-fast and --ease-standard, so an Implementation gap: line would keep the record accurate until they follow.

[Automated review]

Comment on lines +77 to +78
* The touch press's measured release clock, kept as a reference value. Press
* releases now play the theme's `--duration-exit`.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Miss, non-blocking: "now" narrates the change. Suggested:

 * The touch press's measured release clock, a reference value. A press
 * release plays the theme's `--duration-exit`.

Comment on lines +232 to +235
A press shows at once. Every press release that fades does so on the
theme's exit motion tokens (`--duration-exit`, `--ease-exit`), on every
device and pointer, by the owner's decision (2026-11-03); under Reduce
Motion, `design:reduced-motion` DR2 applies.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Non-blocking: a desktop mouse release on ClickableCard, SelectableCard and Thumbnail still transitions on --duration-fast and --ease-standard (ClickableCard.tsx lines 125-131). Until those follow, an Implementation gap: line here would keep "on every device and pointer" accurate.

@cixzhang
cixzhang marked this pull request as ready for review November 4, 2026 20:27
@cixzhang cixzhang added the ci:run A maintainer lets this outside contributor's pull request run CI (AST-030 FR17) label Nov 4, 2026
@cixzhang
cixzhang marked this pull request as draft November 4, 2026 20:30
@cixzhang
cixzhang marked this pull request as ready for review November 4, 2026 20:30
@github-actions

github-actions Bot commented Nov 4, 2026 •

Copy link
Copy Markdown
Contributor

PR Analysis Report

🔎 Preview · 82dd709

Storybook · Sandbox · built from this PR's head

Modified components

Component Size LoC Visual · A11y · RTL
CommandPalette 🔴 56.2 kB (+2.3 kB) · 12.3 kB CSS (−16 B) — — · — · —
lab/ChatEmojiPicker 🔴 68.6 kB (+2.2 kB) · 773 B CSS (0) — — · — · —
lab/ChatReactionBar 🔴 69.2 kB (+2.2 kB) · 1.1 kB CSS (0) — — · — · —
184 more components
Component Size LoC Visual · A11y · RTL
ContextMenuItem 🔴 23.8 kB (+2.2 kB) · 6.0 kB CSS (−52 B) — — · — · —
DateRangeInput 🔴 74.0 kB (+2.2 kB) · 11.2 kB CSS (−32 B) — — · — · —
MultiSelector 🔴 75.9 kB (+2.2 kB) · 15.3 kB CSS (−24 B) — — · — · —
lab/TourStep 🔴 60.7 kB (+2.2 kB) · 590 B CSS (0) — — · — · —
Tokenizer 🔴 72.8 kB (+2.2 kB) · 17.1 kB CSS (−29 B) — — · — · —
Popover 🔴 54.8 kB (+2.2 kB) · 12.7 kB CSS (−26 B) — — · — · —
lab/CommentComposer 🔴 107.5 kB (+2.1 kB) · 1.9 kB CSS (0) — — · — · —
Carousel 🔴 52.4 kB (+2.1 kB) · 9.5 kB CSS (−31 B) — — · — · —
lab/Schedule 🔴 63.3 kB (+2.1 kB) · 3.9 kB CSS (0) — — · — · —
richtext/RichTextEditorToolbar 🔴 231.3 kB (+2.1 kB) · 454 B CSS (0) — — · — · —
Selector 🔴 81.9 kB (+2.1 kB) · 16.1 kB CSS (−51 B) — — · — · —
lab/TransferListSelector 🔴 86.0 kB (+2.1 kB) · 1.9 kB CSS (0) — — · — · —
Table 🔴 87.5 kB (+2.1 kB) · 16.6 kB CSS (−55 B) — — · — · —
Pagination 🔴 90.7 kB (+2.1 kB) · 16.4 kB CSS (−51 B) — — · — · —
lab/TransferList 🔴 78.3 kB (+2.0 kB) · 1.7 kB CSS (0) — — · — · —
TableHeaderCell 78.8 kB (+2.0 kB) · 16.1 kB CSS (−54 B) — — · — · —
TableCell 79.2 kB (+2.0 kB) · 16.3 kB CSS (−55 B) — — · — · —
ContextMenu 77.9 kB (+1.9 kB) · 15.9 kB CSS (−49 B) — — · — · —
DropdownMenu 76.6 kB (+1.9 kB) · 16.0 kB CSS (−54 B) — — · — · —
MoreMenu 76.9 kB (+1.9 kB) · 16.0 kB CSS (−54 B) — — · — · —
lab/ListInput 84.1 kB (+1.7 kB) · 1.6 kB CSS (0) — — · — · —
Markdown 148.3 kB (+1.6 kB) · 18.8 kB CSS (−56 B) — — · — · —
ClickableCard 16.5 kB (+939 B) · 6.9 kB CSS (−38 B) — — · — · —
SelectableCard 16.6 kB (+920 B) · 7.2 kB CSS (−38 B) — — · — · —
CommandPaletteItem 11.7 kB (+904 B) · 3.6 kB CSS (−28 B) — — · — · —
SegmentedControlItem 12.1 kB (+899 B) · 4.0 kB CSS (−33 B) — — · — · —
Tab 13.0 kB (+891 B) · 4.2 kB CSS (−31 B) — — · — · —
TopNavItem 12.4 kB (+888 B) · 4.0 kB CSS (−34 B) — — · — · —
DropdownMenuRadioItem 20.7 kB (+906 B) · 6.3 kB CSS (−53 B) — — · — · —
DropdownMenuCheckboxItem 20.7 kB (+904 B) · 6.3 kB CSS (−53 B) — — · — · —
Token 27.2 kB (+878 B) · 4.7 kB CSS (−30 B) — — · — · —
TopNavMegaMenuItem 12.5 kB (+873 B) · 4.2 kB CSS (−35 B) — — · — · —
SelectorOption 18.9 kB (+881 B) · 5.7 kB CSS (−51 B) — — · — · —
DropdownMenuItem 19.9 kB (+878 B) · 5.9 kB CSS (−54 B) — — · — · —
Outline 23.5 kB (+857 B) · 4.1 kB CSS (−33 B) — — · — · —
richtext/RichTextEditor 279.7 kB (+819 B) · 2.6 kB CSS (0) — — · — · —
Item 15.5 kB (+865 B) · 5.2 kB CSS (−55 B) — — · — · —
NumberInput 56.5 kB (+821 B) · 10.1 kB CSS (−30 B) — — · — · —
SideNav 74.9 kB (+818 B) · 10.1 kB CSS (−33 B) — — · — · —
lab/EmojiPicker 72.1 kB (+780 B) · 722 B CSS (0) — — · — · —
CheckboxInput 50.0 kB (+813 B) · 8.7 kB CSS (−34 B) — — · — · —
lab/SelectableCardGroup 51.7 kB (+774 B) · 162 B CSS (0) — — · — · —
lab/DiffViewer 72.7 kB (+770 B) · 2.1 kB CSS (0) — — · — · —
InputGroup 43.9 kB (+797 B) · 7.3 kB CSS (−30 B) — — · — · —
ChatComposerInput 60.8 kB (+797 B) · 10.0 kB CSS (−31 B) — — · — · —
Step 29.6 kB (+797 B) · 5.6 kB CSS (−31 B) — — · — · —
ChatComposerTokenElement 60.8 kB (+796 B) · 10.0 kB CSS (−31 B) — — · — · —
Link 44.1 kB (+794 B) · 6.8 kB CSS (−30 B) — — · — · —
TopNav 57.2 kB (+790 B) · 9.6 kB CSS (−32 B) — — · — · —
Slider 92.1 kB (+790 B) · 8.3 kB CSS (−36 B) — — · — · —
Stepper 48.2 kB (+780 B) · 8.8 kB CSS (−31 B) — — · — · —
TextInput 54.3 kB (+781 B) · 9.9 kB CSS (−32 B) — — · — · —
ChatComposer 62.8 kB (+779 B) · 10.5 kB CSS (−31 B) — — · — · —
FileInput 55.1 kB (+775 B) · 9.6 kB CSS (−32 B) — — · — · —
CheckboxList 45.4 kB (+765 B) · 7.5 kB CSS (−29 B) — — · — · —
ChatLayout 49.7 kB (+765 B) · 9.2 kB CSS (−32 B) — — · — · —
Switch · Storybook 89.7 kB (+775 B) · 9.5 kB CSS (−47 B) 1,717 (0) — · — · —
richtext/RichTextView 260.1 kB (+726 B) · 2.3 kB CSS (0) — — · — · —
TextArea 49.0 kB (+755 B) · 8.8 kB CSS (−32 B) — — · — · —
CodeBlock 60.5 kB (+749 B) · 10.0 kB CSS (−32 B) — — · — · —
MobileNav 55.7 kB (+747 B) · 9.3 kB CSS (−33 B) — — · — · —
Lightbox 53.8 kB (+747 B) · 9.1 kB CSS (−34 B) — — · — · —
ComplexSelector 57.0 kB (+743 B) · 10.4 kB CSS (−31 B) — — · — · —
SideNavItem 56.1 kB (+745 B) · 9.8 kB CSS (−33 B) — — · — · —
Collapsible 24.6 kB (+737 B) · 4.5 kB CSS (−29 B) — — · — · —
BaseTypeahead 56.7 kB (+749 B) · 9.6 kB CSS (−43 B) — — · — · —
Typeahead 64.5 kB (+736 B) · 11.2 kB CSS (−32 B) — — · — · —
AlertDialog 87.8 kB (+725 B) · 13.1 kB CSS (−23 B) — — · — · —
SideNavCollapseButton 47.4 kB (+734 B) · 8.7 kB CSS (−32 B) — — · — · —
ToggleButton 47.4 kB (+730 B) · 8.8 kB CSS (−31 B) — — · — · —
Banner 48.5 kB (+730 B) · 9.2 kB CSS (−32 B) — — · — · —
lab/CommentPin 48.3 kB (+690 B) · 1.2 kB CSS (0) — — · — · —
ChatLayoutScrollButton 47.1 kB (+715 B) · 8.9 kB CSS (−31 B) — — · — · —
Thumbnail 50.9 kB (+715 B) · 10.2 kB CSS (−32 B) — — · — · —
Calendar 55.7 kB (+715 B) · 9.3 kB CSS (−33 B) — — · — · —
DialogHeader 49.4 kB (+711 B) · 10.2 kB CSS (−30 B) — — · — · —
SideNavHeading 61.0 kB (+714 B) · 10.0 kB CSS (−33 B) — — · — · —
MobileNavToggle 46.9 kB (+711 B) · 8.7 kB CSS (−31 B) — — · — · —
DrawerHeader 49.6 kB (+708 B) · 11.6 kB CSS (−30 B) — — · — · —
ChatDictationButton 47.1 kB (+707 B) · 8.8 kB CSS (−31 B) — — · — · —
ChatSendButton 47.0 kB (+707 B) · 8.7 kB CSS (−31 B) — — · — · —
TopNavMegaMenu 55.6 kB (+691 B) · 10.6 kB CSS (−20 B) — — · — · —
AvatarGroupOverflow 40.1 kB (+700 B) · 5.4 kB CSS (−31 B) — — · — · —
Button · Storybook 46.5 kB (+690 B) · 8.7 kB CSS (−31 B) 628 (0) — · — · —
TopNavMenu 60.4 kB (+690 B) · 9.9 kB CSS (−33 B) — — · — · —
IconButton 46.6 kB (+684 B) · 8.7 kB CSS (−31 B) — — · — · —
TopNavHeading 60.4 kB (+684 B) · 9.8 kB CSS (−31 B) — — · — · —
TableSelectionToolbar 56.1 kB (+683 B) · 11.8 kB CSS (−32 B) — — · — · —
TimeInput 139.1 kB (+674 B) · 14.5 kB CSS (−24 B) — — · — · —
TreeList 40.8 kB (+699 B) · 5.3 kB CSS (−52 B) — — · — · —
TabMenu 57.7 kB (+675 B) · 9.8 kB CSS (−30 B) — — · — · —
DateInput 152.8 kB (+643 B) · 15.5 kB CSS (−24 B) — — · — · —
BreadcrumbItem 70.6 kB (+660 B) · 11.2 kB CSS (−58 B) — — · — · —
AppShell 74.4 kB (+590 B) · 12.2 kB CSS (−33 B) — — · — · —
PowerSearch 245.8 kB (+595 B) · 22.2 kB CSS (−41 B) — — · — · —
DropdownMenuSubMenu 59.0 kB (+546 B) · 9.2 kB CSS (−57 B) — — · — · —
RadioListItem 53.0 kB (+530 B) · 9.3 kB CSS (−62 B) — — · — · —
DateTimeInput 174.8 kB (+487 B) · 17.2 kB CSS (−24 B) — — · — · —
CheckboxListItem 55.2 kB (+515 B) · 10.3 kB CSS (−57 B) — — · — · —
ListItem 54.5 kB (+510 B) · 10.3 kB CSS (−57 B) — — · — · —
SegmentedControl 83.6 kB (+477 B) · 6.7 kB CSS (−31 B) — — · — · —
Overlay 21.5 kB (+363 B) · 3.9 kB CSS (−35 B) — — · — · —
LayerProvider 64.1 kB (+256 B) · 9.4 kB CSS (−33 B) — — · — · —
Toast 60.3 kB (+198 B) · 9.0 kB CSS (−31 B) — — · — · —
lab/ChatTypingIndicator 25.0 kB (+162 B) · 612 B CSS (0) — — · — · —
lab/SVGIcon 7.8 kB (+159 B) · 764 B CSS (0) — — · — · —
charts/ChartAxis 6.9 kB (+157 B) · 112 B CSS (0) — — · — · —
lab/LogStream 8.1 kB (+155 B) · 1.6 kB CSS (0) — — · — · —
lab/ChartDotGLInteractive 8.5 kB (+154 B) · 20 B CSS (0) — — · — · —
lab/ChatReasoning 7.1 kB (+154 B) · 967 B CSS (0) — — · — · —
lab/CircularProgress 8.6 kB (+154 B) · 1.1 kB CSS (0) — — · — · —
lab/ChartDotGL 7.5 kB (+153 B) · 20 B CSS (0) — — · — · —
lab/Stat 4.3 kB (+153 B) · 646 B CSS (0) — — · — · —
lab/ChartStreamGL 7.6 kB (+151 B) · 20 B CSS (0) — — · — · —
lab/ChartHeatmapGL 8.6 kB (+150 B) · 20 B CSS (0) — — · — · —
lab/ChatUnreadDivider 3.7 kB (+148 B) · 348 B CSS (0) — — · — · —
lab/ThreeDScatterGL 7.8 kB (+148 B) · 20 B CSS (0) — — · — · —
BottomSheetSwitcher 17.4 kB (+174 B) · 3.4 kB CSS (−28 B) — — · — · —
CommandPaletteList 16.1 kB (+163 B) · 3.4 kB CSS (−27 B) — — · — · —
ChatSystemMessage 7.0 kB (+160 B) · 3.8 kB CSS (−26 B) — — · — · —
MetadataListItem 6.7 kB (+161 B) · 3.5 kB CSS (−27 B) — — · — · —
NavHeadingMenu 15.5 kB (+162 B) · 3.5 kB CSS (−28 B) — — · — · —
AvatarStatusDot 7.3 kB (+161 B) · 3.5 kB CSS (−28 B) — — · — · —
ButtonGroup 9.1 kB (+161 B) · 3.4 kB CSS (−28 B) — — · — · —
Toolbar 35.0 kB (+166 B) · 7.8 kB CSS (−33 B) — — · — · —
FormLayout 6.5 kB (+160 B) · 3.5 kB CSS (−28 B) — — · — · —
CommandPaletteEmpty 6.4 kB (+158 B) · 3.5 kB CSS (−27 B) — — · — · —
ToggleButtonGroup 6.6 kB (+159 B) · 3.4 kB CSS (−28 B) — — · — · —
TypeaheadItem 6.4 kB (+162 B) · 3.5 kB CSS (−31 B) — — · — · —
Grid 4.6 kB (+158 B) · 3.8 kB CSS (−28 B) — — · — · —
Section 7.7 kB (+156 B) · 6.3 kB CSS (−26 B) — — · — · —
TableRow 6.7 kB (+160 B) · 3.9 kB CSS (−30 B) — — · — · —
Card 6.7 kB (+155 B) · 6.3 kB CSS (−26 B) — — · — · —
LayoutPanel 7.8 kB (+157 B) · 4.9 kB CSS (−28 B) — — · — · —
TableFooter 3.5 kB (+157 B) · 3.3 kB CSS (−28 B) — — · — · —
TopNavMegaMenuFeaturedCard 7.1 kB (+157 B) · 3.6 kB CSS (−28 B) — — · — · —
Center 4.4 kB (+157 B) · 4.6 kB CSS (−29 B) — — · — · —
Code 3.7 kB (+153 B) · 3.5 kB CSS (−25 B) — — · — · —
GridSpan 3.6 kB (+157 B) · 3.3 kB CSS (−29 B) — — · — · —
OverflowList 8.8 kB (+159 B) · 3.6 kB CSS (−31 B) — — · — · —
TableBody 3.5 kB (+156 B) · 3.3 kB CSS (−28 B) — — · — · —
TableHeader 3.5 kB (+156 B) · 3.3 kB CSS (−28 B) — — · — · —
ChatMessageBubble 7.2 kB (+151 B) · 3.7 kB CSS (−24 B) — — · — · —
ChatMessageMetadata 19.9 kB (+151 B) · 4.1 kB CSS (−24 B) — — · — · —
InputGroupText 6.6 kB (+155 B) · 3.8 kB CSS (−28 B) — — · — · —
MetadataList 16.9 kB (+152 B) · 3.7 kB CSS (−25 B) — — · — · —
SideNavSection 6.8 kB (+157 B) · 3.7 kB CSS (−30 B) — — · — · —
Skeleton 4.0 kB (+153 B) · 3.7 kB CSS (−26 B) — — · — · —
CommandPaletteFooter 17.2 kB (+154 B) · 3.7 kB CSS (−28 B) — — · — · —
NavIcon 3.7 kB (+154 B) · 3.4 kB CSS (−28 B) — — · — · —
CommandPaletteGroup 3.7 kB (+150 B) · 3.4 kB CSS (−25 B) — — · — · —
DropdownMenuGroup 6.3 kB (+153 B) · 3.4 kB CSS (−28 B) — — · — · —
DropdownMenuRadioGroup 6.3 kB (+155 B) · 3.3 kB CSS (−30 B) — — · — · —
ResizeHandle 19.7 kB (+155 B) · 4.3 kB CSS (−30 B) — — · — · —
AspectRatio 3.9 kB (+151 B) · 3.6 kB CSS (−28 B) — — · — · —
CollapsibleGroup 6.6 kB (+153 B) · 3.3 kB CSS (−30 B) — — · — · —
ChatComposerDrawer 17.7 kB (+156 B) · 4.7 kB CSS (−34 B) — — · — · —
TabList 35.6 kB (+151 B) · 6.3 kB CSS (−29 B) — — · — · —
Badge 4.2 kB (+151 B) · 4.0 kB CSS (−30 B) — — · — · —
Blockquote 3.7 kB (+148 B) · 3.5 kB CSS (−27 B) — — · — · —
ChatTokenizedText 7.2 kB (+151 B) · 4.0 kB CSS (−30 B) — — · — · —
Citation 20.2 kB (+149 B) · 4.4 kB CSS (−29 B) — — · — · —
ChatMessage 16.8 kB (+149 B) · 3.7 kB CSS (−30 B) — — · — · —
Breadcrumbs 16.1 kB (+145 B) · 3.4 kB CSS (−31 B) — — · — · —
Kbd 16.8 kB (+145 B) · 3.6 kB CSS (−31 B) — — · — · —
Timestamp 21.4 kB (+115 B) · 8.9 kB CSS (−30 B) — — · — · —
charts/Chart 160.9 kB (+60 B) · 494 B CSS (0) — — · — · —
lab/CodeEditor 14.1 kB (+36 B) · 743 B CSS (0) — — · — · —
ProgressBar 10.9 kB (+41 B) · 6.2 kB CSS (−20 B) — — · — · —
ChatMessageList 22.9 kB (+45 B) · 6.8 kB CSS (−30 B) — — · — · —
CommandPaletteInput 26.9 kB (+41 B) · 7.4 kB CSS (−29 B) — — · — · —
ChatToolCalls 26.0 kB (+37 B) · 8.2 kB CSS (−31 B) — — · — · —
Timer 9.6 kB (+33 B) · 5.8 kB CSS (−29 B) — — · — · —
BottomSheet 55.1 kB (0) · 7.5 kB CSS (0) — — · — · —
List 5.4 kB (0) · 435 B CSS (0) — — · — · —
StatusDot 22.9 kB (+1 B) · 5.2 kB CSS (−30 B) — — · — · —
Avatar 34.8 kB (−10 B) · 5.4 kB CSS (−30 B) — — · — · —
Drawer 40.5 kB (0) · 8.2 kB CSS (−45 B) — — · — · —
AvatarGroup 37.5 kB (−32 B) · 5.5 kB CSS (−29 B) — — · — · —
lab/Comments 265.5 kB (−84 B) · 2.5 kB CSS (0) — — · — · —
lab/CommentThread 260.2 kB (−132 B) · 2.4 kB CSS (0) — — · — · —
FieldLabel 37.8 kB (−304 B) · 4.8 kB CSS (−595 B) — — · — · —
Field 41.7 kB (−340 B) · 6.3 kB CSS (−590 B) — — · — · —
RadioList 43.1 kB (−389 B) · 6.4 kB CSS (−590 B) — — · — · —

Package size: @astryxdesign/core 6.43 MB packed (−1.4 kB); no new dependencies.

API changes: none in this pull request

Committed API report behind this build: cli 8 rows, core 2 rows; run pnpm api:report.

Wide change (shared styles: packages/core/src/theme/themeMotion.ts, packages/core/src/utils/interactionOverlay.stylex.ts, packages/core/src/utils/rowPressLayer.stylex.ts): add ci:run-visual, ci:run-a11y or ci:run-rtl to run them.


Generated by PR Enrichment workflow | View full report

@cixzhang
cixzhang merged commit 7f8de29 into main Nov 4, 2026
86 of 120 checks passed
cixzhang added a commit that referenced this pull request Nov 5, 2026
…t curve

After #9890 the row's touch release plays the theme's exit tokens, whose
curve leaves fastest at its end. The video's 40 ms frames rarely land in
the last few milliseconds before Linux WebKit's end-of-animation
hand-back, so the "within 1 of rest" check failed most runs. The case now
sets a 400 ms exit on the row, reads the clock and curve from the page,
and judges rest as the curve's value one recording frame before the end.
cixzhang added a commit that referenced this pull request Nov 5, 2026
…t curve

After #9890 the row's touch release plays the theme's exit tokens, whose
curve leaves fastest at its end. The video's 40 ms frames rarely land in
the last few milliseconds before Linux WebKit's end-of-animation
hand-back, so the "within 1 of rest" check failed most runs. The case now
sets a 400 ms exit on the row, reads the clock and curve from the page,
and judges rest as the curve's value one recording frame before the end.
cixzhang added a commit that referenced this pull request Nov 5, 2026
…t curve

After #9890 the row's touch release plays the theme's exit tokens, whose
curve leaves fastest at its end. The video's 40 ms frames rarely land in
the last few milliseconds before Linux WebKit's end-of-animation
hand-back, so the "within 1 of rest" check failed most runs. The case now
sets a 400 ms exit on the row, reads the clock and curve from the page,
and judges rest as the curve's value one recording frame before the end.
@github-actions
github-actions Bot deleted the fix/press-release-exit-tokens branch November 5, 2026 06:03
cixzhang added a commit that referenced this pull request Nov 5, 2026
…t curve (#10011)

* test(core): the WebKit row release video proof judges rest on the exit curve

After #9890 the row's touch release plays the theme's exit tokens, whose
curve leaves fastest at its end. The video's 40 ms frames rarely land in
the last few milliseconds before Linux WebKit's end-of-animation
hand-back, so the "within 1 of rest" check failed most runs. The case now
sets a 400 ms exit on the row, reads the clock and curve from the page,
and judges rest as the curve's value one recording frame before the end.

* Merge branch 'main' into fix/list-row-webkit-video-exit-curve

* Merge branch 'main' into fix/list-row-webkit-video-exit-curve

* Merge branch 'main' into fix/list-row-webkit-video-exit-curve

This branch was successfully deployed

1 active deployment
Preview — 82dd7099 Deployed Nov 4, 2026 by vercel[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ci:run A maintainer lets this outside contributor's pull request run CI (AST-030 FR17) CLA Signed This label is managed by the Meta Open Source bot. needs:design-review Affects visuals — Design should review

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant