Skip to content

spec(List): a touch row's press paint and the animated layout handle for row updates (FR11–FR12) - #8687

Merged
cixzhang merged 10 commits into
meta:mainfrom
vjeux:uikit/c11-list-spec-amend
Oct 27, 2026
Merged

cixzhang merged 10 commits into
meta:mainfrom
vjeux:uikit/c11-list-spec-amend

Conversation

@vjeux

@vjeux vjeux commented Oct 27, 2026 •

Copy link
Copy Markdown
Contributor

Review only this PR's change: vjeux/astryx@55b54e5...8909823 (depends on #8571, the approved FR10 record).

Exact decision needed

May component:List admit a touch row's press paint and its adoption of the animated layout handle?

Existing authority searched

component:List, spec:AST-094 (FR4 roles, FR5 compositor, FR11 cell profile, FR13 touch gate), spec:AST-105 (the one animated layout handle, FR4 one shared start), spec:AST-103 DEC-4 (itemKey), design:user-states DR1. #8077 and #8106 implement these.

Decision

  • FR11: under a coarse pointer, an interactive row's press follows the cell profile: the --color-overlay-pressed token above its background and below its content, no element added, released on the press release roles on the compositor; at rest the row is as it was.
  • FR12: List takes an animatedLayout handle and reports inserted, removed and moved rows, each identified by its itemKey; with it, every part starts on the same frame on the shared role under every pointer, and without it the list changes at once. Approving FR12 changes feat(List): animate row inserts, removals and moves through the animatedLayout handle #8106's API (the handle replaces hasAnimatedChanges) and its pointer gate.
  • OQ1: whether a caller's ::before must survive a press.

Dividers, the selection hold and edit mode stay out until their owner answers.

Rejected alternatives

  • A List-owned boolean for row updates (spec:AST-105 FR6).

Claim scope and non-goals

List rows only; not TreeList, the press controller, or reorder mode.

Evidence and implementation relationship

iOS 26.2 UITableView read on the simulator; the implementations carry red-first proofs. Prettier re-pads the contract table only.

Writing rubric results

  • R1 narration: none; each claim states what a row does.
  • R2 research: none in the record.
  • R3 evidence naming a change: none; bases name UIKit behavior and records.
  • R4 rejected alternatives: none in the record.
  • R5 references: none in the record.
  • R6 open questions: OQ1 is unanswered and keeps its two options.

Scope

  • This PR contains specification records only.
  • It records observable behavior and preserves equivalent internal implementations.
  • Any named internal mechanism is intentionally public, names its dependent caller/system, and explains why an equivalent implementation would not satisfy the contract.
  • Verification states the evidence layer and failure signal without prescribing CI job/workflow topology.
  • It records one intentional durable decision, not a rescue for a separable tagalong.
  • The canonical knowledge owner, affected current claims, and overlapping open work are named; any ownership collision is resolved or called out for human decision.
  • Adjacent API, visual, accessibility, composition, and implementation facts remain outside scope unless this exact decision depends on them.
  • Public text and artifacts contain no internal Meta context.

Validation

pnpm check:knowledge (aligned), Prettier and git diff --check: clean.

vjeux and others added 5 commits October 26, 2026 11:17
List's FR2 keeps the `padded` treatment's row geometry everywhere. Under a
coarse primary pointer, a new FR10 lets a default or spacious ListItem row
reach the iOS 26.2 UITableView row heights: at least 52 px, and 62 px with a
description. Compact rows and fine pointers keep their geometry, and a
theme's `min-height` on the `list-item` target still wins. FR2, the allowed
variations, the `padded` representative state and the verification map name
the exception.
…rification row states failure and audit

The allowed-variation bullet promised every row a 44 px target, while FR10
grows a row's target toward 44 px only where its neighbors leave room and
clamps it to half a gap: it now says so and cites FR10. FR10's verification
row gains its failure expectation and its audit section
(`audit:List/layout`), like the map's other rows.
… animated layout, and edit mode (FR11–FR16)

Draft claims for an engineering owner's approval: under a coarse pointer a
pressed row's dividers give way (FR11), the press paints through one layer on
the row's ::before (FR12), and a row tapped to push stays selected until the
pop (FR13); row updates animate through the shared animated layout handle
(FR14); edit mode makes room for its control beyond the applied inset (FR15),
and its selection control is announced as a checked state (FR16, AR3). DEC-5
records the touch-only rule and its one exception; OQ1 asks how edit mode
composes with reorder mode.
@vercel

vercel Bot commented Oct 27, 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 4:49pm UTC

Request Review

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

astracat-bot Bot commented Oct 27, 2026 •

Copy link
Copy Markdown

AI review status for this pull request.

Review status Updated
🟢 Reviewed (for maintainers only) Oct 27, 2026, 5:17 PM UTC

@cixzhang

Copy link
Copy Markdown
Contributor

Posted by Cindy's agent on her behalf.

Thanks for the List touch-row record. Here's how it maps onto current decisions:

  • FR14 (row updates animate through the animated-layout handle under every pointer; the handle replaces hasAnimatedChanges): already decided by spec:AST-105 FR1 and one-API-per-job. Fine as written.
  • FR12: please state the outcome rather than the mechanism ("the press paint adds no element"), not "one layer on the row's ::before". Note the caller-::before concern raised on fix(core): a control's press release runs on the compositor #8118.
  • FR11 (a pressed row's dividers give way to its highlight) is a visual press treatment. Cindy decided to keep today's pressed overlay with no new press treatment, so please drop FR11 for now. It can come back with a theme-owned pressed-treatment proposal.
  • FR13 (a tapped row stays selected while its page is open) and edit mode (FR15, FR16, AR3, OQ1: isEditing and editingControl) are new questions. They're going to Cindy, so please keep them out of this PR, or mark them proposed, until she answers.

If this stays idle, we'll make these edits after about 30 minutes, keeping your authorship.

…ndle; the rest waits for its owner answers

Per the owner's review: FR11 states the press paint's outcome (no element
added) rather than its mechanism, and OQ1 asks whether a caller's ::before
must survive a press; FR12 is the animated layout handle. The dividers'
press treatment, the selection hold and edit mode leave this record until
their owner answers.
@cixzhang

Copy link
Copy Markdown
Contributor

/approve-spec f9a03a0

@github-actions github-actions Bot added spec-auto-merge Auto-merge was enabled by the spec owner gate and removed needs:spec-owner-review Current knowledge records await owner approval labels Oct 27, 2026
@vjeux vjeux changed the title spec(List): touch list rows: dividers, press layer, selection hold, animated layout, edit mode (FR11–FR16) spec(List): a touch row's press paint and the animated layout handle for row updates (FR11–FR12) Oct 27, 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.

Changes requested: an engineering owner approved this List record's direction, but FR12 conflicts with the current animated layout spec, and a few record fixes are needed before it merges.

  • FR12 holds a new row's fade until crossing rows have cleared it and gives a removed row a one-second deadline, while spec:AST-105 FR4 starts the changed row and the rows after it on the same frame on one shared motion role; reword FR12, or amend AST-105 FR4 in this pull request.
  • "Rows need stable keys" should name itemKey, which spec:AST-103 DEC-4 makes a List row's one identity.
  • FR11's "cell press strength" and "cell release curve" are not defined by spec:AST-094 FR11; name the token and the motion role, and cite FR5 for the compositor.
  • The Contract at a glance table should list animatedLayout, the touch behavior and the two new governing specs, and the two "owns only" sentences in Family and system relationships should agree.

A new commit resets the spec approval, so an engineering owner, the author included, re-records it by commenting /approve-spec <full head SHA>.

[Automated review]

Comment thread packages/core/src/List/List.spec.md Outdated
| FR9 | The list element containing the rows MUST clip in the inline axis with `overflow-inline: clip`, never `hidden`. Under `outset` and `bleed` its inline edges MUST reach the host's padding edge, so the clip never cuts resting row paint and a swiped row paints no further than that edge. | `spec:AST-057/FR9` | Verified by `List.test.tsx` and real-browser geometry |
| FR10 | Under a coarse primary pointer (`spec:AST-094` FR13), every ListItem row MUST offer a hit target at least 44 px tall, through its padding or an invisible hit area, with no visual change, where its neighbors leave room: the hit area never overlaps a neighboring row's or control's target, and between close neighbors it is clamped to half the gap; row height and geometry stay as they are at every density. A fine pointer keeps today's hit target. | Owner decision, 2026-10-26: no row-height change, a 44 px touch target | Accepted contract |
| FR11 | Under a coarse primary pointer, an interactive row's press MUST paint above its background and below its content without adding an element, at the cell press strength, and its release MUST fade on the cell release curve on the compositor (`spec:AST-094` FR11). At rest the row's paint and stacking are as they were. | `spec:AST-094` FR11, the cell press model | Proposed; awaiting an engineering owner's approval |
| FR12 | List MUST take an `animatedLayout` handle (`spec:AST-105` FR1) and report each row inserted, removed, or moved between renders. With a handle, an inserted row fades in once rows moving past have cleared it, a removed row collapses in place and leaves within one second, a row crossing rows that move the other way rides above them on the list's surface, and the rows after a change glide to their new places (`spec:AST-105` FR3), all on the shared motion role (`spec:AST-105` FR4). Without a handle the list changes at once (`spec:AST-105` FR2). Rows need stable keys. | `spec:AST-105` FR1–FR5; UIKit `UITableView` batch updates, iOS 26.2 | Proposed; awaiting an engineering owner's approval |

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

FR12's "an inserted row fades in once rows moving past have cleared it" and "leaves within one second" conflict with spec:AST-105 FR4, which has the changed row and the rows after it read one motion role and "both start on the same frame", never with per-component timing. Start the fade on the glide's first frame and leave the exit's length to the role, or amend AST-105 FR4 for list rows in this pull request. "Rows need stable keys" should also name itemKey, the one row identity spec:AST-103 DEC-4 settles.

Comment thread packages/core/src/List/List.spec.md Outdated
| FR8 | `outset` and `bleed` are valid only under a host state whose published inline inset matches its applied padding: a visually neutral host, such as a Layout region with explicit padding or a padded ScrollableArea, or the content area of a Card, Section (any variant), Dialog, or BottomSheet. Those hosts bound their padding with a border, background, or clip; FR6 keeps row paint inside the padding edge, so it never covers the border or changes the host's outline. Automatic LayoutContent/LayoutPanel states with a known publication mismatch are not eligible until that gap is fixed, and Drawer's content area is not admitted until it has its own evidence. | `architecture:container-padding/INV8–INV11`; real-browser evidence in each admitted host | Accepted contract |
| FR9 | The list element containing the rows MUST clip in the inline axis with `overflow-inline: clip`, never `hidden`. Under `outset` and `bleed` its inline edges MUST reach the host's padding edge, so the clip never cuts resting row paint and a swiped row paints no further than that edge. | `spec:AST-057/FR9` | Verified by `List.test.tsx` and real-browser geometry |
| FR10 | Under a coarse primary pointer (`spec:AST-094` FR13), every ListItem row MUST offer a hit target at least 44 px tall, through its padding or an invisible hit area, with no visual change, where its neighbors leave room: the hit area never overlaps a neighboring row's or control's target, and between close neighbors it is clamped to half the gap; row height and geometry stay as they are at every density. A fine pointer keeps today's hit target. | Owner decision, 2026-10-26: no row-height change, a 44 px touch target | Accepted contract |
| FR11 | Under a coarse primary pointer, an interactive row's press MUST paint above its background and below its content without adding an element, at the cell press strength, and its release MUST fade on the cell release curve on the compositor (`spec:AST-094` FR11). At rest the row's paint and stacking are as they were. | `spec:AST-094` FR11, the cell press model | Proposed; awaiting an engineering owner's approval |

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

spec:AST-094 FR11 defines only the cell profile's timing (a highlight 150 ms after touch-down that drops when a scroll wins). No record defines a "cell press strength" or "cell release curve", and AST-094 FR4 requires a touch curve to be a named motion role. Name the overlay token and strength and the release's motion role, and cite FR5 for the compositor.

…le; FR11 names its token and roles

Per review: FR12 follows spec:AST-105 FR4 (the changed rows and the rows
after them start on the same frame on the shared role) and names itemKey as
a row's identity (spec:AST-103 DEC-4); FR11 names the cell profile, the
pressed overlay token and the press release roles, and cites FR5; the
contract at a glance lists animatedLayout, the touch behavior and the two
governing specs; the ownership sentences agree.
@github-actions github-actions Bot added needs:spec-owner-review Current knowledge records await owner approval and removed spec-auto-merge Auto-merge was enabled by the spec owner gate labels Oct 27, 2026
@cixzhang

Copy link
Copy Markdown
Contributor

/approve-spec 3edd236

@github-actions github-actions Bot added spec-auto-merge Auto-merge was enabled by the spec owner gate and removed needs:spec-owner-review Current knowledge records await owner approval labels Oct 27, 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.

Changes requested: an engineering owner approved this List record's direction, but FR11 cites motion roles the touch presentations spec does not define, and a few record fixes remain before it merges.

  • FR11 calls timing.press.highlightOutMs and timing.press.highlightOutCurve spec:AST-094 FR4 roles, but FR4 and the role registry keep them as internal constants; name them as the press model's release duration and curve (or add them to FR4 here), and drop design:user-states DR1 from the basis, since that record covers only its listed components.
  • The End-user impact, Builder impact and Compatibility/readiness rows should cover the touch target, the press and the new animatedLayout prop, including that it is additive and not implemented yet.
  • FR12 should say a collapsing removed row is inert and hidden from assistive technology until it is gone, word or drop the verification row's one-second bound, and say what a row without an itemKey does.

A new commit resets the spec approval, so an engineering owner, the author included, re-records it by commenting /approve-spec <full head SHA>.

[Automated review]

Comment thread packages/core/src/List/List.spec.md Outdated
| FR8 | `outset` and `bleed` are valid only under a host state whose published inline inset matches its applied padding: a visually neutral host, such as a Layout region with explicit padding or a padded ScrollableArea, or the content area of a Card, Section (any variant), Dialog, or BottomSheet. Those hosts bound their padding with a border, background, or clip; FR6 keeps row paint inside the padding edge, so it never covers the border or changes the host's outline. Automatic LayoutContent/LayoutPanel states with a known publication mismatch are not eligible until that gap is fixed, and Drawer's content area is not admitted until it has its own evidence. | `architecture:container-padding/INV8–INV11`; real-browser evidence in each admitted host | Accepted contract |
| FR9 | The list element containing the rows MUST clip in the inline axis with `overflow-inline: clip`, never `hidden`. Under `outset` and `bleed` its inline edges MUST reach the host's padding edge, so the clip never cuts resting row paint and a swiped row paints no further than that edge. | `spec:AST-057/FR9` | Verified by `List.test.tsx` and real-browser geometry |
| FR10 | Under a coarse primary pointer (`spec:AST-094` FR13), every ListItem row MUST offer a hit target at least 44 px tall, through its padding or an invisible hit area, with no visual change, where its neighbors leave room: the hit area never overlaps a neighboring row's or control's target, and between close neighbors it is clamped to half the gap; row height and geometry stay as they are at every density. A fine pointer keeps today's hit target. | Owner decision, 2026-10-26: no row-height change, a 44 px touch target | Accepted contract |
| FR11 | Under a coarse primary pointer, an interactive row's press MUST follow the cell profile (`spec:AST-094` FR11): it paints the `--color-overlay-pressed` token above the row's background and below its content without adding an element, and its release fades on the press release roles (`timing.press.highlightOutMs`, `timing.press.highlightOutCurve`; `spec:AST-094` FR4) on the compositor (FR5). At rest the row's paint and stacking are as they were. | `spec:AST-094` FR4, FR5, FR11; `design:user-states` DR1 | Proposed; awaiting an engineering owner's approval |

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

timing.press.highlightOutMs and timing.press.highlightOutCurve are not spec:AST-094 FR4 roles: FR4's table lists no press role, and on main the timing table registers only stateChangeMs and four curves.* roles, keeping the press clocks as internal constants (roles.test.ts asserts that set). Name them as the press model's release duration and curve, or add them to FR4 in this pull request. design:user-states DR1 is also not a basis for List rows: its matrix "is the complete current claim" and approves no other component.

Comment thread packages/core/src/List/List.spec.md Outdated
| FR9 | The list element containing the rows MUST clip in the inline axis with `overflow-inline: clip`, never `hidden`. Under `outset` and `bleed` its inline edges MUST reach the host's padding edge, so the clip never cuts resting row paint and a swiped row paints no further than that edge. | `spec:AST-057/FR9` | Verified by `List.test.tsx` and real-browser geometry |
| FR10 | Under a coarse primary pointer (`spec:AST-094` FR13), every ListItem row MUST offer a hit target at least 44 px tall, through its padding or an invisible hit area, with no visual change, where its neighbors leave room: the hit area never overlaps a neighboring row's or control's target, and between close neighbors it is clamped to half the gap; row height and geometry stay as they are at every density. A fine pointer keeps today's hit target. | Owner decision, 2026-10-26: no row-height change, a 44 px touch target | Accepted contract |
| FR11 | Under a coarse primary pointer, an interactive row's press MUST follow the cell profile (`spec:AST-094` FR11): it paints the `--color-overlay-pressed` token above the row's background and below its content without adding an element, and its release fades on the press release roles (`timing.press.highlightOutMs`, `timing.press.highlightOutCurve`; `spec:AST-094` FR4) on the compositor (FR5). At rest the row's paint and stacking are as they were. | `spec:AST-094` FR4, FR5, FR11; `design:user-states` DR1 | Proposed; awaiting an engineering owner's approval |
| FR12 | List MUST take an `animatedLayout` handle (`spec:AST-105` FR1) and report each row inserted, removed, or moved between renders. With a handle, an inserted row enters, a removed row collapses in place, and a row crossing rows that move the other way rides above them on the list's surface, while the rows after a change glide to their new places (`spec:AST-105` FR3), all starting on the same frame on the shared motion role (`spec:AST-105` FR4). Without a handle the list changes at once (`spec:AST-105` FR2). A row's identity is its ListItem's `itemKey` (`spec:AST-103` DEC-4). | `spec:AST-105` FR1–FR5; `spec:AST-103` DEC-4 | Proposed; awaiting an engineering owner's approval |

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 removed row that collapses in place stays on screen after removal; please state that it is inert and hidden from assistive technology until it is gone (as spec:AST-103 FR5 says of its drag preview), and what a row without an itemKey does. The FR12 verification row's "past one second" bound is not stated here; if it is architecture:component-style-authoring INV7's exit-copy cleanup, INV7 counts it from the end of the transition.

Comment thread packages/core/src/List/List.spec.md Outdated
Comment on lines +48 to +50
| End-user impact | Row text can share the line of the list header and a heading above, with row paint stopping at the text, reaching into the host padding, or reaching the host edges. |
| Builder impact | One `edge` choice per list. `flush` works anywhere; `outset` and `bleed` act only inside a host that publishes container padding. |
| Compatibility/readiness | Additive; omission keeps current geometry; `edgeCompensation` keeps working with a codemod to `edge`. `reorderable` and `itemKey` are additive and stable, specified and not implemented yet; without them nothing changes. |

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

These rows still describe only edge treatment. architecture:knowledge-contracts asks End-user impact to name who is affected, Builder impact every new caller choice, and Compatibility/readiness the additive status and implementation state: please cover the touch target and press (FR10, FR11) and the new animatedLayout prop, which is additive and specified but not implemented.

…d row out of reach, and the glance rows cover the new claims

Per review: FR11's release is the press model's internal release duration
and curve, with its basis narrowed to spec:AST-094 FR5 and FR11; FR12 makes
a collapsing removed row inert and hidden from assistive technology until
it is gone, and changes a row without an itemKey at once, and its
verification row drops the one-second bound; the end-user, builder and
compatibility rows cover the touch target, the press and the additive,
not yet implemented animatedLayout prop.
@github-actions github-actions Bot added needs:spec-owner-review Current knowledge records await owner approval and removed spec-auto-merge Auto-merge was enabled by the spec owner gate labels Oct 27, 2026
@cixzhang

Copy link
Copy Markdown
Contributor

/approve-spec d71d6bc

@meta-cla meta-cla Bot added the CLA Signed This label is managed by the Meta Open Source bot. label Oct 27, 2026
@github-actions github-actions Bot added spec-auto-merge Auto-merge was enabled by the spec owner gate and removed needs:spec-owner-review Current knowledge records await owner approval labels Oct 27, 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.

Changes requested: an engineering owner approved this List record's direction at this revision and the earlier conflicts with the touch presentations and animated layout specs are fixed, but a few record fixes remain before it merges.

  • FR12's verification row fails a removed row's reachability only after its collapse ends; it should also fail a row that takes focus, pointer input or an accessibility-tree node while it collapses, which is what FR12 requires.
  • Builder impact should say rows need an itemKey to animate, and Compatibility/readiness should state that the touch target and the press's compositor release are not implemented yet.
  • The spec:AST-094 relationship line should credit FR4's motion role to FR12, since FR11 no longer reads one.

A new commit resets the spec approval, so an engineering owner, the author included, re-records it by commenting /approve-spec <full head SHA>.

[Automated review]

Comment thread packages/core/src/List/List.spec.md Outdated
| FR2–FR6, FR8–FR9, AR1–AR2 | Real-browser List geometry evidence | each treatment in a Card at two paddings, a Section, an inline Dialog with and without Layout, a BottomSheet, a padded ScrollableArea scrolling vertically and in both axes, a LayoutContent with explicit padding, and standalone; header and dividers; LTR/RTL; hovered and selected rows; a swiped row under `outset` and `bleed` | Header movement, content off the expected line, paint past the host's padding edge, clipped resting paint, or a changed row box fails | `audit:List/visual` |
| FR10 | List tests of the touch hit target and real-browser hit-testing | every density; a row with a description; compact rows packed closer than 44 px; a row with an end control; a coarse and a fine pointer; a theme row padding | A coarse-pointer row whose target stays at its box where its neighbors leave room, a target that reaches a neighboring row's or control's target, a changed row box, or a changed fine-pointer target fails | `audit:List/layout` |
| FR11 | Item press-layer tests and real-browser pixel evidence | press, hold, and release; a release while the main thread is blocked; a mouse | A release that stops while script runs, an element added for the press, or paint or stacking changed at rest fails | `audit:List/visual` |
| FR12 | List update-motion tests and real-browser frame evidence | an insert, a removal, and a reorder, with and without a handle; reduced motion; a mouse | A staying row that jumps with a handle, motion without one, a removed row left in place or reachable by assistive technology after its collapse ends, or layout or paint per frame fails | `audit:List/visual` |

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

FR12 says a removed row is "inert and hidden from assistive technology until it is gone", but this row fails only "a removed row left in place or reachable by assistive technology after its collapse ends", and no representative state has focus inside the removed row or a screen reader. An implementation that keeps the collapsing row in the tab order and the accessibility tree for the whole collapse passes it. Please add those two states and fail a removed row that takes focus, pointer input or an accessibility-tree node during its collapse, or stays in place after it ends (architecture:knowledge-contracts INV18: "A verification map names evidence sufficient to prove a claim").

Comment thread packages/core/src/List/List.spec.md Outdated
Comment on lines +49 to +50
| Builder impact | One `edge` choice per list. `flush` works anywhere; `outset` and `bleed` act only inside a host that publishes container padding. Passing an `animatedLayout` handle is the one new choice; the touch target and press need none. |
| Compatibility/readiness | Additive; omission keeps current geometry; `edgeCompensation` keeps working with a codemod to `edge`. `reorderable` and `itemKey` are additive and stable, specified and not implemented yet; without them nothing changes. `animatedLayout` is additive and specified, not implemented yet; the touch target and press change nothing under a fine pointer. |

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Two gaps against the component projection in architecture:knowledge-contracts: Builder impact calls the handle "the one new choice", but FR12 animates only rows that carry itemKey ("a row without one changes at once"), so keying rows is a second decision; and Compatibility/readiness gives animatedLayout's implementation state but not FR10's or FR11's. On main no List row has a coarse-pointer hit area, and the press release still animates --astryx-press-alpha rather than opacity or transform (packages/core/src/utils/interactionOverlay.stylex.ts), so both are specified and not implemented yet.

Comment thread packages/core/src/List/List.spec.md Outdated
(FR9) and `ListItem` passes `swipeActions` and `swipeBehavior` through to
`Item` unchanged.
- `spec:AST-094` owns the touch presentation gate (FR13), the press model
(FR11), and motion roles (FR4); FR11 applies them to list rows.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

"FR11 applies them to list rows" still credits FR11 with AST-094's motion roles (FR4), but FR11 now uses the press model's own release duration and curve and cites only FR5 and FR11. FR12 is the claim that reads an FR4 role (springs.settle, through spec:AST-105 FR4).

…le; the glance rows name itemKey and what is not implemented

Per review: FR12's verification row also fails a collapsing removed row that
takes focus, pointer input or an accessibility-tree node; Builder impact
says rows animate only with an itemKey; Compatibility/readiness says the
touch target and the press's compositor release are specified and not
implemented yet; the spec:AST-094 relationship credits its motion role to
FR12, and the gate and press model to FR10 and FR11.
@cixzhang

Copy link
Copy Markdown
Contributor

/approve-spec f28f347

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

Changes requested: an engineering owner approved this List record's direction at this revision and the earlier record fixes are in, but two record details would land wrong.

  • FR11 and FR12 still say "Proposed; awaiting an engineering owner's approval" and the Animated layout concept still says proposed, so the current record would call them undecided after this approval; give them the accepted status FR10 uses.
  • The Ownership boundary's Owns list still covers only the edge treatment; add the rows' touch target, press paint and update motion that FR10–FR12 and the Family line now give List.

A new commit resets the spec approval, so an engineering owner, the author included, re-records it by commenting /approve-spec <full head SHA>.

[Automated review]

Comment thread packages/core/src/List/List.spec.md Outdated
Comment on lines +125 to +126
| FR11 | Under a coarse primary pointer, an interactive row's press MUST follow the cell profile (`spec:AST-094` FR11): it paints the `--color-overlay-pressed` token above the row's background and below its content without adding an element, and its release fades over the press model's release duration and curve on the compositor (`spec:AST-094` FR5). At rest the row's paint and stacking are as they were. | `spec:AST-094` FR5, FR11 | Proposed; awaiting an engineering owner's approval |
| FR12 | List MUST take an `animatedLayout` handle (`spec:AST-105` FR1) and report each row inserted, removed, or moved between renders. With a handle, an inserted row enters, a removed row collapses in place, inert and hidden from assistive technology until it is gone, and a row crossing rows moving the other way rides above them on the list's surface, while the rows after a change glide to their new places (`spec:AST-105` FR3), all starting on one frame on the shared motion role (`spec:AST-105` FR4). Without a handle the list changes at once (`spec:AST-105` FR2). A row's identity is its `itemKey` (`spec:AST-103` DEC-4); a row without one changes at once. | `spec:AST-105` FR1–FR5; `spec:AST-103` DEC-4 | Proposed; awaiting an engineering owner's approval |

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

FR11 and FR12 still read "Proposed; awaiting an engineering owner's approval", but an engineering owner approved this exact revision, and once it merges they sit in an authority: current record beside FR10's "Accepted contract". The component template says "A current contract contains no unresolved rows" (docs/templates/knowledge/component-spec.md). Please give both the status FR10 uses, with the owner decision as their basis; the new commit then needs a fresh /approve-spec.

Comment thread packages/core/src/List/List.spec.md Outdated
| ------------------------------ | ------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------ | ---------------------------------------------------------------------------------------- | -------- | ---------------- | ---------- | -------------------------------------------- |
| Edge treatment | `padded`, `flush`, `outset`, `bleed` | Where row content and row paint sit relative to the list's edges and the host's padding | Every density, marker style, and divider setting; `outset` and `bleed` read host padding | `padded` | `component:List` | accepted | Other values are rejected by the public type |
| Edge compensation (deprecated) | omitted, `inline` | Same as `edge="outset"` | As `outset` | omitted | `component:List` | deprecated | Other values are rejected by the public type |
| Animated layout | absent, a `useAnimatedLayout` handle | Inserted, removed, and moved rows animate, and the rows after a change glide to their new places (FR12) | Every density, marker style, edge treatment, and divider setting | absent | `spec:AST-105` | proposed | Other values are rejected by the public type |

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 approval in, this concept should read accepted, like Reordering below it; as proposed the current record says the prop is still undecided.

Comment on lines +197 to +198
List owns the collection-level treatment, row placement, and its rows' own
entering, exiting, and crossing (FR12).

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 line now gives List its rows' entering, exiting and crossing, but the Ownership boundary's Owns list (L86–92) still names only the edge treatment, its alias, the header and the inset relationship. architecture:knowledge-contracts INV14 scopes current authority to the claims inside a record's stated ownership boundary, so please add the FR10–FR12 row behavior there.

…pted status; List owns its rows' touch target, press paint and update motion

Per review: FR11 and FR12 take FR10's accepted status and the Animated
layout concept is accepted, matching the engineering owner's approval; the
ownership boundary lists the rows' touch target (FR10), press paint (FR11)
and update motion (FR12).
@cixzhang

Copy link
Copy Markdown
Contributor

/approve-spec 8909823

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

This component:List record looks ready to merge: an engineering owner approved FR10–FR12, PR2 and OQ1 at this exact head, and the touch-presentation, animated-layout and reordering claims they cite still support them on main. Two small record fixes would help, before or after merge:

  • In FR12, say how a move that a reorder drop commits plays once, since spec:AST-103 FR1 and FR3 already give the drop its own settle and travel.
  • Add interaction and accessibility to review_triggers, so pnpm specs:for routes the touch and accessibility baselines to List's files.

Any new commit needs a fresh /approve-spec <full head SHA> from an engineering owner.

[Automated review]

| FR9 | The list element containing the rows MUST clip in the inline axis with `overflow-inline: clip`, never `hidden`. Under `outset` and `bleed` its inline edges MUST reach the host's padding edge, so the clip never cuts resting row paint and a swiped row paints no further than that edge. | `spec:AST-057/FR9` | Verified by `List.test.tsx` and real-browser geometry |
| FR10 | Under a coarse primary pointer (`spec:AST-094` FR13), every ListItem row MUST offer a hit target at least 44 px tall, through its padding or an invisible hit area, with no visual change, where its neighbors leave room: the hit area never overlaps a neighboring row's or control's target, and between close neighbors it is clamped to half the gap; row height and geometry stay as they are at every density. A fine pointer keeps today's hit target. | Owner decision, 2026-10-26: no row-height change, a 44 px touch target | Accepted contract |
| FR11 | Under a coarse primary pointer, an interactive row's press MUST follow the cell profile (`spec:AST-094` FR11): it paints the `--color-overlay-pressed` token above the row's background and below its content without adding an element, and its release fades over the press model's release duration and curve on the compositor (`spec:AST-094` FR5). At rest the row's paint and stacking are as they were. | `spec:AST-094` FR5, FR11 | Accepted contract |
| FR12 | List MUST take an `animatedLayout` handle (`spec:AST-105` FR1) and report each row inserted, removed, or moved between renders. With a handle, an inserted row enters, a removed row collapses in place, inert and hidden from assistive technology until it is gone, and a row crossing rows moving the other way rides above them on the list's surface, while the rows after a change glide to their new places (`spec:AST-105` FR3), all starting on one frame on the shared motion role (`spec:AST-105` FR4). Without a handle the list changes at once (`spec:AST-105` FR2). A row's identity is its `itemKey` (`spec:AST-103` DEC-4); a row without one changes at once. | `spec:AST-105` FR1–FR5; `spec:AST-103` DEC-4 | Accepted contract |

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Optional: spec:AST-103 FR1 settles a dropped item on its slot and FR3 gives the other rows and the drop their own travel, so a List with both reorderable and animatedLayout has two claims moving the same rows at the commit. One sentence saying a move a reorder commits plays once (for example, from where the preview settled) would keep the implementation from failing AST-105's "an element moved twice for one frame".

spec:AST-002/DEC-2,
spec:AST-017/FR4,
spec:AST-057/FR9,
spec:AST-094,

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Optional: with FR10–FR12 the record carries touch-interaction and assistive-technology claims, but review_triggers above stays [public-api, behavior, layout, theming]. pnpm specs:for packages/core/src/List/List.tsx routes 148 distinct global claims from those triggers and 196 with interaction and accessibility added (for example design:bidirectionality DR8 and architecture:interaction-modality INV4), so adding both would show them to the implementing pull requests.

@cixzhang
cixzhang merged commit 02c6cf3 into meta:main Oct 27, 2026
48 checks passed
@vjeux
vjeux deleted the uikit/c11-list-spec-amend branch October 27, 2026 17:23
@cixzhang

Copy link
Copy Markdown
Contributor

Posted by Cindy's agent on her behalf.

Thanks for the iOS edit-mode research; it was useful. Cindy decided on a different direction for edit mode. No List-level mode and no isEditing or editingControl props. Instead, apps compose edit experiences themselves by changing what they put in a row's startContent and endContent: a checkbox to select, a delete control, a reorder handle. Those slot changes animate through the List's animated-layout handle, so the control enters and the row's content glides to make room on one shared clock. A small record change for that composition path will follow.

@cixzhang

Copy link
Copy Markdown
Contributor

Posted by Cindy's agent on her behalf.

Following up on my earlier comment: Cindy approved the composition approach for edit experiences. List gains no edit mode and no new props. A row reports changes to its startContent and endContent (including the reorder handle appearing) to the List's animated-layout handle: new content enters, leaving content exits, content replaced in a slot swaps in place, and the rest of the row glides to make room. A control that leaves is inert while it exits, and focus moves to the row's main target. A List record change and the implementation will follow as separate PRs.

This branch was successfully deployed

1 active deployment
Preview — 8909823c 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. spec-auto-merge Auto-merge was enabled by the spec owner gate

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants