Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
108 commits
Select commit Hold shift + click to select a range
f1b86d7
test(interaction): real touch input for browser interaction proofs
vjeux Oct 24, 2026
4076bf3
spec(AST-094): touch presentations follow UIKit
vjeux Oct 24, 2026
28343b4
chore(core): the UIKit constants table for touch presentations
vjeux Oct 24, 2026
c88087c
chore(core): UIKit's spring, decay, rubber-band and projection math
vjeux Oct 24, 2026
081b6c5
feat(core): gesture recognizer core — UIKit's state machine and the a…
vjeux Oct 24, 2026
f423ffe
feat(core): tap and long-press recognizers with UIKit's measured thre…
vjeux Oct 24, 2026
4dc2aae
feat(core): one touch presentation resolver
vjeux Oct 24, 2026
706683b
fix(build): resolve defineConsts read across files in astryxStylex
vjeux Oct 24, 2026
2a8b491
chore(core): UIKit's spring, decay, rubber-band and projection math
vjeux Oct 24, 2026
60fc05c
chore(core): a compositor animator for touch presentations
vjeux Oct 24, 2026
968b85f
fix(interaction): release only the lifted finger on a partial lift in…
vjeux Oct 24, 2026
6f2b3e0
test(interaction): curve sampling and deterministic storyboards
vjeux Oct 24, 2026
eef784b
fix(interaction): curves end before a held end value; rest judges pre…
vjeux Oct 24, 2026
dbbdebc
test(interaction): frame evidence and the BottomSheet exemplar
vjeux Oct 24, 2026
6bd39ce
test(interaction): make the busy-main-thread verdict robust to a load…
vjeux Oct 24, 2026
5cb0543
feat(core): pan gesture recognizer with UIKit's hysteresis and velocity
vjeux Oct 24, 2026
7d58f27
feat(core): swipe, pinch, rotation, screen-edge pan and hover recogni…
vjeux Oct 24, 2026
1a76704
feat(core): touch-action derivation, native scroll probe and haptics
vjeux Oct 24, 2026
cfffebf
feat(core): gesture host — claims, click suppression and the browser'…
vjeux Oct 24, 2026
0453495
feat(core): UIControl press tracking, press profiles, the press paint…
vjeux Oct 24, 2026
398d4eb
test(core): gesture browser proof in Chromium and WebKit, and the README
vjeux Oct 24, 2026
e9f1e0a
chore(core): the animator plays any curve, drives a pseudo-element, s…
vjeux Oct 24, 2026
90c34de
Merge the interaction harness (#8045) under the animator's browser pr…
vjeux Oct 24, 2026
f328e32
chore(core): useAnimator and the animator's browser proofs on the int…
vjeux Oct 24, 2026
9d2d720
feat(core): the touch presentation resolver knows the iOS idiom
vjeux Oct 24, 2026
765a094
feat(core): themes retune touch motion through motion roles
vjeux Oct 24, 2026
f87a453
Merge the theme's motion roles into the animator branch
vjeux Oct 24, 2026
65fb64b
feat(core): the animator plays each table spring and curve as its the…
vjeux Oct 24, 2026
5f79e11
Merge the gesture system (#8074) under the experimental touch exports
vjeux Oct 24, 2026
8f0d9c7
Merge the touch presentation resolver (#8062) under the experimental …
vjeux Oct 24, 2026
eaf2189
feat(core): experimental motion and gesture subpaths for touch presen…
vjeux Oct 24, 2026
7065daf
fix(core): one touch model on every device; the adaptive change is a …
cixzhang Oct 24, 2026
92ef66c
Merge main into wip/uikit-pr-touch-presentation
cixzhang Oct 24, 2026
398c723
fix(core): the touch resolver reads the theme's compact definition
cixzhang Oct 24, 2026
33ee284
docs(MoreMenu): keep the doc's own formatting; change only the compac…
cixzhang Oct 24, 2026
63e5356
fix(core): the animator's Reduced Motion follows design:reduced-motion
vjeux Oct 24, 2026
18ff410
fix(core): under Reduced Motion, travel lands with a plain write whil…
vjeux Oct 24, 2026
512b368
Merge #8062 (the touch resolver reads the theme's compact definition)…
vjeux Oct 24, 2026
1203525
Merge commit '706683bb99' into uikit/pr-export-t2
vjeux Oct 24, 2026
0268a58
test(build): the cross-file constants fixture keys on a width, not it…
vjeux Oct 24, 2026
38edf28
chore(core): the constants table names only what exists, and dates ev…
vjeux Oct 24, 2026
0783fcd
fix(core): paging past the last page lands on a real page
vjeux Oct 24, 2026
b419011
fix(core): an identity at rest leaves the element
vjeux Oct 24, 2026
8103ede
fix(core): the animator's model holds a curve's start until the brows…
vjeux Oct 24, 2026
cea95bb
test(core): a fixed child stays fixed after a motion back to identity
vjeux Oct 24, 2026
1dcf753
fix(core): theme motion role ids are checked against the generated li…
vjeux Oct 24, 2026
5aafeaf
fix(core): a motion reads a theme switched earlier in the same task
vjeux Oct 24, 2026
a5ec352
fix(core): resolveMotion observes and listens to nothing
vjeux Oct 24, 2026
6f81139
Merge #8075 (defineConsts read across files) into the experimental su…
vjeux Oct 24, 2026
9d8226d
feat(core): the Reduce Motion media keys are StyleX constants
vjeux Oct 24, 2026
fe9fbba
fix(core): reading a motion table registers nothing, and a theme ship…
vjeux Oct 25, 2026
9fff2ac
fix(core): under Reduced Motion, two calls in one frame both land
vjeux Oct 25, 2026
14fe728
feat(core): export the Reduce Motion keys for other packages
vjeux Oct 25, 2026
7c604ea
test(lab): say what the Reduce Motion keys import test proves
vjeux Oct 25, 2026
dbd6d17
fix(core): Reduce Motion keys stay literal in a transition
vjeux Oct 25, 2026
0b81c86
fix(core): a retarget of a curve the browser has not started keeps it…
vjeux Oct 25, 2026
970c908
fix(core): a call on the clock of a waiting call from rest starts wit…
vjeux Oct 25, 2026
7091f8b
fix(core): experimental touch hooks stay out of stable search and doc…
vjeux Oct 25, 2026
9960f84
refactor(core): export the animator's settle thresholds
vjeux Oct 25, 2026
65ac34a
test(core): a move during a Reduce Motion dip's fade out ends visible
vjeux Oct 25, 2026
5cb103f
fix(core): a time ahead reads a waiting curve from its call's time
vjeux Oct 25, 2026
49bb28a
fix(core): under Reduce Motion, only a call's own opacity makes it an…
vjeux Oct 25, 2026
189de88
fix(core): theme adaptations have no platform condition
vjeux Oct 25, 2026
601b54e
refactor(core): the animator reads a coarse pointer through TOUCH_QUERY
vjeux Oct 25, 2026
874ca93
docs(core): theme motion examples name a role that exists
vjeux Oct 25, 2026
2164696
fix(core): a page registers and ships only the motion tables it anima…
vjeux Oct 25, 2026
3e2d5e3
test(core): the role registry test checks every table discovery regis…
vjeux Oct 25, 2026
b496085
Merge main into the experimental subpaths (lab typechecks with its te…
vjeux Oct 25, 2026
e90e445
feat(core): a held finger never starts text selection on a touch control
vjeux Oct 24, 2026
b1d37f1
refactor(core): the gesture barrels no longer export VelocityStrategy
vjeux Oct 25, 2026
7618bd8
test(core): the theme browser proof registers the springs table it re…
vjeux Oct 25, 2026
ab35d4b
docs(core): state how a decay behaves under Reduce Motion
vjeux Oct 25, 2026
9dc4ae9
docs(cli): the theme template names no platform condition
vjeux Oct 25, 2026
8b790ed
fix(Item): a list row's touch press release runs on the compositor
vjeux Oct 24, 2026
510fff4
feat(List): a touch press hides the dividers beside the pressed row
vjeux Oct 24, 2026
d413dd3
chore(core): the press feedback's selection lock is a [fix], the gest…
vjeux Oct 25, 2026
230cca0
fix(core): gesture host fixes from review
vjeux Oct 24, 2026
2dc3c06
fix(core): gesture hooks follow their element; recognizer plumbing is…
vjeux Oct 24, 2026
3026425
feat(core): claimsTouches: false makes a gesture watcher
vjeux Oct 24, 2026
eeba10e
refactor(core): the gesture host and scroll probe read direction thro…
vjeux Oct 24, 2026
2315647
feat(core): the gesture host holds the page still for a scroll lock
vjeux Oct 24, 2026
175f962
feat(core): the gesture host tells a finger's scroll from the program's
vjeux Oct 24, 2026
3936e16
feat(core): the gesture host counts the fingers on the screen
vjeux Oct 24, 2026
2553d39
feat(core): a scroll that ends while its finger rests stays the finge…
vjeux Oct 24, 2026
369725b
feat(core): touch gates, and a second finger gives a one-finger pan up
vjeux Oct 25, 2026
5fd5ae8
feat(core): a delivered press keeps its touch from the browser's pan
vjeux Oct 25, 2026
2f26f13
chore: changeset for the gesture host as the one document touch owner
vjeux Oct 25, 2026
301f7af
fix(core): keepsTouch is opt-in per press tracker
vjeux Oct 25, 2026
ec2c0a8
fix(core): a second finger fails only a one-finger pan that has not c…
vjeux Oct 25, 2026
1dbf13f
fix(core): detaching a keepsTouch press tracker removes its blocking …
vjeux Oct 25, 2026
cc7cd47
feat(List): a row tapped to push stays selected until the pop deselec…
vjeux Oct 24, 2026
45b76b7
feat(List): rows under a finger are as tall as iOS table rows
vjeux Oct 24, 2026
1f3cd26
feat(TreeList): rows expand and collapse the way an iOS outline list …
vjeux Oct 24, 2026
d8a812b
feat(TreeList): page content below the tree moves with an expansion
vjeux Oct 24, 2026
94bd93d
feat(List): hasAnimatedChanges moves rows the way an iOS table animat…
vjeux Oct 24, 2026
24ef5e8
refactor(core): row motions use the motion foundation's shared animat…
vjeux Oct 24, 2026
c2b4397
fix(List): a new row fades in once the rows crossing it have cleared,…
vjeux Oct 24, 2026
1c39442
fix(List): a removed row collapses in place, the row below glued to i…
vjeux Oct 24, 2026
bccc72c
fix(List): the update motion reads nothing when off and moves only co…
vjeux Oct 24, 2026
347822e
fix(List): under reduced motion the update motion cross-fades
vjeux Oct 24, 2026
65bfcb2
fix(List): a removed row collapses as it was on screen
vjeux Oct 24, 2026
92054ad
chore(core): a table's reorder values and model, measured on iOS 26.2
vjeux Oct 24, 2026
d1a0ed8
Merge main (with the shared edge autoscroll, #8334) under the List re…
vjeux Oct 25, 2026
32ae681
Merge the gesture host as the one document touch owner (#8336) under …
vjeux Oct 25, 2026
1797464
feat(List): onReorder reorders rows the way an iOS table does
vjeux Oct 25, 2026
e96e626
feat(List): a reorder handle's moves, and ListItem reorderLabel
vjeux Oct 24, 2026
c35b3cc
Merge the List reorder's moves (and #8139's stack) under the experime…
vjeux Oct 25, 2026
8b8779e
feat(core): an experimental List reorder subpath for rows that are no…
vjeux Oct 24, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions .changeset/build-stylex-cross-file-consts.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
'@astryxdesign/build': patch
---

[fix] `astryxStylex` resolves `defineConsts` values read from another file. With the `{stylexOptions}` form (the one Storybook uses), a file that read only constants from a `.stylex.ts` module lost that import once StyleX compiled it, so the constants never reached the CSS: a constant used as a media-query key failed the build ("Invalid empty selector") and one used as a value shipped as a custom property nothing declares. A constant defined on the library side of the layer split and read on the product side stayed unresolved in either form. A production build now also warns, naming the variable and the rule that reads it, when its stylesheet reads a StyleX-generated custom property that nothing declares; set `undefinedVariables: 'error'` to fail the build instead.

@vjeux
7 changes: 7 additions & 0 deletions .changeset/gesture-browser-negotiation.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
'@astryxdesign/core': patch
---

[chore] Touch-action derivation, the native scroll probe and haptics for the gesture system. Not exported from the package root; touch presentations reach them through the experimental subpaths (see their entry). No component uses them yet.

@vjeux
7 changes: 7 additions & 0 deletions .changeset/gesture-hook-fixes.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
'@astryxdesign/core': patch
---

[experimental] Gesture hooks follow their element: `useGestureRecognizer` and `usePressTracker` attach to a node rendered after mount or swapped behind the same ref, and call the consumer back neither from cleanup nor after unmount. `usePressTracker` takes `isBraking` (by default the host's) and applies a changed `trackingExpansion`, `highlightDelay`, `cancelTravel` or `quickTapFlash` from the next touch. The recognizer's arena plumbing (`arena`, `pending`, touch delivery, `applyState`, `resetToPossible` and the failure and simultaneity checks) is now `protected`. `attachTapHaptic` gives focus straight back from its hidden switch and adds none to a label that already labels another control.

@vjeux
7 changes: 7 additions & 0 deletions .changeset/gesture-host-fixes.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
'@astryxdesign/core': patch
---

[experimental] Gesture host fixes: a scroll the page makes under a still finger (scrollIntoView, a pinned transcript, scroll anchoring) no longer cancels the press or swallows its click; recognizers that never claim (`claimsTouches` false) get no blocking `touchmove` listener, and a finger's target listener is passive unless a recognizer on that touch can claim; a claimed pen holds only its own stylus touches; an element's own `touch-action` is never widened; content slotted into a shadow-tree scroller scrolls with it; the delegated press stays idle while the document press controller holds the same attribute.

@vjeux
7 changes: 7 additions & 0 deletions .changeset/gesture-host-owner.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
'@astryxdesign/core': patch
---

[experimental] The gesture host becomes the one document-level touch owner: `holdPageScroll(decide)` keeps a scroll lock's page still, `watchFingerScrolls` / `isFingerScroll` tell a finger's scroll from the program's, `fingersDown()` counts the fingers on the screen, and `addTouchGate(gate)` holds touches away from a presenting layer. A second finger landing anywhere gives a one-finger pan up so the browser can pinch, a press tracker created with `keepsTouch: true` (opt-in, for continuous-tracking controls) keeps its touch from the browser's pan once its press is delivered, and the host reads the writing direction through `isRtlElement`.

@vjeux
7 changes: 7 additions & 0 deletions .changeset/gesture-host.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
'@astryxdesign/core': patch
---

[chore] The gesture system's DOM host (claims, click suppression, the browser's takeover, the pointer behind a contact). Not exported from the package root; touch presentations reach it through the experimental subpaths (see their entry). No component uses it yet.

@vjeux
7 changes: 7 additions & 0 deletions .changeset/gesture-pan.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
'@astryxdesign/core': patch
---

[chore] The pan gesture recognizer, with UIKit's measured hysteresis and velocity filter. Not exported from the package root; touch presentations reach it through the experimental subpaths (see their entry). No component uses it yet.

@vjeux
7 changes: 7 additions & 0 deletions .changeset/gesture-press-tracking.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
'@astryxdesign/core': patch
---

[chore] UIControl press tracking with control and cell profiles, the shared press paint, delegated press tracking and the gesture hooks. Not exported from the package root; touch presentations reach them through the experimental subpaths (see their entry). No component uses them yet.

@vjeux
7 changes: 7 additions & 0 deletions .changeset/gesture-readme.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
'@astryxdesign/core': patch
---

[chore] The gesture system's README for component authors, with its browser proof in Chromium and WebKit.

@vjeux
7 changes: 7 additions & 0 deletions .changeset/gesture-recognizer-core.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
'@astryxdesign/core': patch
---

[chore] The gesture recognizer core for touch presentations: UIKit's recognizer state machine and the arena that settles which recognizer owns a touch. Not exported from the package root; touch presentations reach it through the experimental subpaths (see their entry). No component uses it yet.

@vjeux
7 changes: 7 additions & 0 deletions .changeset/gesture-swipe-pinch-rotation-edge-hover.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
'@astryxdesign/core': patch
---

[chore] Swipe, pinch, rotation, screen-edge pan and hover gesture recognizers. Not exported from the package root; touch presentations reach them through the experimental subpaths (see their entry). No component uses them yet.

@vjeux
7 changes: 7 additions & 0 deletions .changeset/gesture-tap-long-press.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
'@astryxdesign/core': patch
---

[chore] Tap and long-press gesture recognizers with UIKit's measured thresholds. Not exported from the package root; touch presentations reach them through the experimental subpaths (see their entry). No component uses them yet.

@vjeux
7 changes: 7 additions & 0 deletions .changeset/gesture-watcher.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
'@astryxdesign/core': patch
---

[experimental] New recognizer option `claimsTouches: false` makes a watcher: it never claims a touch, so it gets only passive listeners and never delays a scroll, it runs alongside every other recognizer, and it follows a touch the browser takes for a scroll to the lift.

@vjeux
7 changes: 7 additions & 0 deletions .changeset/list-dividers-hide-on-press.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
'@astryxdesign/core': patch
---

[feat] In a `List` with `hasDividers`, a touch press hides the dividers on either side of the pressed row, so the pressed row reads as one unbroken highlight; both come back the moment the finger lifts, while the highlight fades. This applies under any finger (a coarse primary pointer); with a mouse the dividers stay drawn.

@vjeux
7 changes: 7 additions & 0 deletions .changeset/list-has-animated-changes.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
'@astryxdesign/core': patch
---

[feat] `List` gains `hasAnimatedChanges`. Under a finger (a coarse primary pointer, iOS and Android alike), when rows are inserted, removed or reordered, the rows that stay slide to their new places and new rows fade in once the rows sliding past have cleared them, on the spring an iOS table uses. A row that crosses rows moving the other way (a reorder) rides above them with the surface color behind it, as an iOS table's opaque cell does. A removed row collapses in place (a swiped one with its action showing) while the rows below slide up into its gap, as a deleted iOS table cell does. Page content below the list moves with its rows; `followingContent="stays"` keeps it still. With reduced motion on, nothing travels: rows cross-fade into place. Off by default; with a mouse nothing moves.

@vjeux
7 changes: 7 additions & 0 deletions .changeset/list-on-reorder.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
'@astryxdesign/core': patch
---

[feat] `List` takes `onReorder(fromIndex, toIndex)`: each row gets a reorder handle at its end, and `ListItem`'s new `isReorderDisabled` keeps a row in place. On a touch screen a finger held still on a handle picks up its row the way an iOS table's reorder control does (a flick on it still scrolls): the row follows the finger, the rows it passes slide out of its way, the page scrolls near the edges, and on release the row settles into its new place on UIKit's springs. A mouse drags a handle at once, and rows take their places without motion. From the keyboard, a handle's arrow keys, Home and End move its row, Space picks it up and Escape puts it back; every move is announced once it lands.

@vjeux
7 changes: 7 additions & 0 deletions .changeset/list-reorder-experimental.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
'@astryxdesign/core': patch
---

[experimental] `@astryxdesign/core/List/experimental` exports core `List`'s reorder session for lists whose rows are not `ListItem`s, outside the stable compatibility promise (it may change or be removed in a patch release): `useListReorder`, `ListReorderContext`, `ListReorderHandle` and `LIST_REORDER_FIXED_ROW_ATTRIBUTE`. Nothing is added to the package root or to the `List` subpath.

@vjeux
7 changes: 7 additions & 0 deletions .changeset/list-reorder-moves.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
'@astryxdesign/core': patch
---

[feat] A reorderable `List`'s handle, activated without a drag (a tap, a click, a screen reader's double tap), opens its row's moves: Move up, Move down, Move to top and Move to bottom, each offered only when it moves the row, so a row can be reordered with a single pointer and no drag. `ListItem`'s new `reorderLabel` names the handle of a row whose label is not plain text.

@vjeux
7 changes: 7 additions & 0 deletions .changeset/list-row-press-compositor.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
'@astryxdesign/core': patch
---

[fix] A list row's touch press release keeps fading while the page runs script. `ListItem`, `Item` and `TreeList` rows used to stay fully pressed after the finger lifted until the main thread was free, and every frame of the fade repainted the row; the release now runs on the compositor, with the same color, clock and curve as before. Under a finger, an interactive row's press paints on its `::before`: StyleX merges a row's own `::before` from `xstyle` with it property by property, so that decoration keeps the layer's `opacity: 0` and is hidden at rest (a `className` rule overrides only the properties it sets); put row decoration on `::after` or a child element. With a mouse or trackpad the row is unchanged: no layer and no new stacking context.

@vjeux
8 changes: 8 additions & 0 deletions .changeset/list-selection-hold.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
---
'@astryxdesign/core': patch
'@astryxdesign/cli': patch
---

[feat] Under a finger, a list row tapped to push can stay selected while the pushed screen covers it, then deselect as the screen pops, as a UIKit table row does; with a mouse the hold is null and the press releases at the lift as before. `holdSelection(event.target)` from `@astryxdesign/core/utils` holds the `ListItem`, `Item` or `TreeList` row under an activation and returns a handle a navigation drives: `animate(1)` runs UIKit's in-transition deselect, `setProgress` follows an interactive pop, `end(false)` selects the row again after a cancelled pop, and `focus()` returns focus to the row, with a keyboard focus ring only when the user last used a keyboard. The deselect runs on the compositor. A divided list keeps the dividers around the held row hidden. The deselect's clock and curve are motion roles a theme can retune (`list.deselect.navigationPopMs`, `list.deselect.navigationPopCurve`, carried by `--motion-list-deselect-navigation-pop-ms` and `--motion-list-deselect-navigation-pop-curve`), and `astryx docs motion` lists them.

@vjeux
7 changes: 7 additions & 0 deletions .changeset/list-touch-row-heights.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
'@astryxdesign/core': patch
---

[feat] Under a finger (a coarse primary pointer, iOS and Android alike), `List` rows are as tall as iOS table rows: at least 52px, 62px with a description, and at least 44px in `density="compact"`, which used to put rows as short as 33px under a finger. Lists with markers (bullets, numbers, Markdown lists) are running text and keep their rows. Lists driven by a mouse or a trackpad are unchanged. A theme that sets `min-height` on `list-item` keeps its own value.

@vjeux
7 changes: 7 additions & 0 deletions .changeset/reduced-motion-record.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
'@astryxdesign/core': patch
---

[fix] The experimental touch animator follows design:reduced-motion. Under Reduce Motion every `animate` and `play` (travel or opacity, on a spring or any curve) becomes an opacity-only cross-fade of 200 ms on a coarse primary pointer, or for a call marked `touchRelease`, and completes at once on any other pointer; nothing moves, scales or springs, and travel lands with a plain style write while the element is transparent, never as an animated transform. `timing.reducedMotionCrossFadeMs` is now 200 ms and is no longer a theme role. The `reducedMotion` and `crossfade` call options are removed; `crossfadeAs` stays. `animator.reducedMotion()` reports the mode for feedback with no fade of its own, `reducedMotionFade()` gives the same fade to code beside the animator, and `reducedMotion.stylex.ts` holds its constants for StyleX transitions.

@vjeux
7 changes: 7 additions & 0 deletions .changeset/reorder-values.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
'@astryxdesign/core': patch
---

[chore] Internal: a table's reorder values in the UIKit constants table (the reorder control's claim, the slides, the drop's settle, the edge autoscroll steps, measured on iOS 26.2) and the reorder model that applies them. Not exported from the package entry point; no component uses them yet.

@vjeux
7 changes: 7 additions & 0 deletions .changeset/touch-experimental-subpaths.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
'@astryxdesign/core': patch
---

[experimental] Two experimental subpaths for building touch presentations, outside the stable compatibility promise (they may change or be removed in a patch release). `@astryxdesign/core/motion/experimental` exports the compositor animator (`createAnimator`, `useAnimator`), UIKit's spring, rubber-band and cubic-bézier math, `resolveMotion` (a motion role's value under the element's theme), and the UIKit constants table as the read-only `uikit` namespace. `@astryxdesign/core/gestures/experimental` exports UIKit-style gesture recognizers (tap, long press, pan, screen-edge pan, swipe, pinch, rotation, hover), `useGestureRecognizer`, `usePressTracker`, `useTouchPresentation`, `readTouchPresentation`, `playHaptic` and `attachTapHaptic`, with the `GestureArena` and `VelocityStrategy` types their options reach. Nothing is added to the package root or to any other subpath.

@vjeux
8 changes: 8 additions & 0 deletions .changeset/touch-motion-theme-roles.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
---
'@astryxdesign/core': patch
'@astryxdesign/cli': patch
---

[feat] Themes can retune touch motion roles. `defineTheme({motion})` takes `springs`, `durations` and `curves` keyed by motion role, the table path of a measured touch motion value (`springs.sheetPresent`, `navigation.transitionMs`), at the root or in an adaptation rule, and writes one `--motion-*` variable per role it sets. A role the theme leaves out keeps its measured default, an unknown role id is refused, and the duration scale (`fast`, `medium`, `ratio`) is optional when a theme sets only roles. No shipped component reads the roles yet. `astryx docs motion` lists every motion role with its CSS variable and default, and the theme authoring guide and template describe the new fields.

@vjeux
7 changes: 7 additions & 0 deletions .changeset/touch-presentation.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
'@astryxdesign/core': patch
---

[feat] `presentation="adaptive"` on DropdownMenu, ContextMenu, MoreMenu, Selector and MultiSelector, and a DropdownMenu's default sub-menu drill-in, now use the theme's compact definition with a coarse primary pointer: a viewport narrower than the theme's `md` point (768px by default) or shorter than 500px. This is a behavior change. The old default was a bottom sheet at 768px wide and below on a coarse pointer. Now a coarse-pointer screen exactly 768px wide keeps the anchored popover, and a phone in landscape (wider than 768px but shorter than 500px) gets the bottom sheet and the drilled-in sub-menu. To pin a component's presentation regardless of the rule, pass `presentation="popover"` or `presentation="bottom-sheet"`. Mouse and keyboard users on desktop see no change, because every case requires a coarse pointer.

@vjeux
7 changes: 7 additions & 0 deletions .changeset/touch-selection-lock-gestures.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
'@astryxdesign/core': patch
---

[experimental] The gesture host takes the same selection lock: for a press-tracked control's contact, and for a recognizer created with the new `preventsTextSelection` option (`@astryxdesign/core/gestures/experimental`) when it would take the touch. It also covers a non-text input under the finger inside such an element (WebKit's own style makes every input selectable), and restores selection when the contact ends. Other pans leave their content selectable.

@vjeux
7 changes: 7 additions & 0 deletions .changeset/touch-selection-lock.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
'@astryxdesign/core': patch
---

[fix] Under a finger or pen, holding a control or a cell that shows the touch press (the press feedback surfaces) no longer starts text selection or the iOS callout, as on UIKit controls. Selection and the callout come back when the finger lifts. Text fields keep their selection, and a mouse keeps desktop selection.

@vjeux
8 changes: 8 additions & 0 deletions .changeset/tree-list-expand-motion.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
---
'@astryxdesign/core': patch
'@astryxdesign/cli': patch
---

[feat] Under a finger (a coarse primary pointer, iOS and Android alike), a `TreeList` row's children slide out from under it as it expands, with the rows below moving down alongside and the chevron turning, and slide back under it as it collapses, as in an iOS outline list. They used to appear and vanish in a single frame. The motion runs on the compositor and keeps going while the page runs script; with reduced motion on, it cross-fades instead of moving. Trees driven by a mouse are unchanged. The outline spring, and the spring of a list's row updates, are motion roles a theme can retune (`list.update.outlineSpring`, `list.update.tableSpring`, carried by `--motion-list-update-outline-spring` and `--motion-list-update-table-spring`), and `astryx docs motion` lists them.

@vjeux
7 changes: 7 additions & 0 deletions .changeset/tree-list-following-content.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
'@astryxdesign/core': patch
---

[feat] Under a finger, page content below a `TreeList` moves with a row's expand and collapse, on the same spring as the rows, instead of jumping. `followingContent="stays"` keeps it still for apps that manage that area themselves.

@vjeux
7 changes: 7 additions & 0 deletions .changeset/uikit-constants-table.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
'@astryxdesign/core': patch
---

[chore] The UIKit constants table for touch presentations (springs, scroll physics, timing curves and navigation values), each value with its source and a checked list of the simulator measurements still owed. Not exported from the package entry point; no component reads it yet.

@vjeux
7 changes: 7 additions & 0 deletions .changeset/uikit-motion-animator-curves.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
'@astryxdesign/core': patch
---

[chore] The touch presentations' animator plays any closed-form curve (such as a spring chasing a moving target), drives a pseudo-element such as a dialog's ::backdrop, follows design:reduced-motion (under Reduce Motion, an opacity-only cross-fade of 200 ms on a coarse pointer or after a touch release and an immediate change on any other pointer, with no option or theme value that keeps travel or lengthens the fade; an entrance or exit role orients a slide that changes no opacity), and starts a call from rest when the browser commits it, as Core Animation does. Not exported from the package root; touch presentations reach it through the experimental subpaths (see their entry).

@vjeux
7 changes: 7 additions & 0 deletions .changeset/uikit-motion-animator.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
'@astryxdesign/core': patch
---

[chore] A compositor animator for touch presentations. It plays UIKit's springs, scroll coasts and any closed-form curve as Web Animations on translate, rotate, scale and opacity, so they keep running while JavaScript is busy, and reads values and velocities back from the curves for interruption, retargeting and Reduce Motion cross-fades. Not exported from the package root; touch presentations reach it through the experimental subpaths (see their entry). No component uses it yet.

@vjeux
7 changes: 7 additions & 0 deletions .changeset/uikit-motion-math.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
'@astryxdesign/core': patch
---

[chore] The spring, decay, rubber-band and projection math of UIKit for touch presentations, as pure functions checked against an independent integration and against values read from UIKit. Not exported from the package root; touch presentations reach it through the experimental subpaths (see their entry). No component uses it yet.

@vjeux
7 changes: 7 additions & 0 deletions .changeset/uikit-motion-use-animator.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
'@astryxdesign/core': patch
---

[chore] UseAnimator, a React wrapper around the touch presentations' animator that never re-renders per frame, and browser proofs on the interaction harness that the animator's motion keeps running through a blocked main thread in Chromium and WebKit. Not exported from the package root; touch presentations reach it through the experimental subpaths (see their entry).

@vjeux
Loading
Loading