@astryxdesign/core 0.7.5-canary.0f3d2f4 → 0.7.5-canary.105bbbe

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@astryxdesign/core",
3
- "version": "0.7.5-canary.0f3d2f4",
3
+ "version": "0.7.5-canary.105bbbe",
4
4
  "displayName": "Astryx Core",
5
5
  "description": "The component library. Accessible, themeable React components with built-in spacing, dark mode, and StyleX styling.",
6
6
  "author": "Meta Open Source",
@@ -847,8 +847,8 @@
847
847
  "react-dom": ">=19.0.0"
848
848
  },
849
849
  "devDependencies": {
850
- "@astryxdesign/a11y-spec": "0.7.5-canary.0f3d2f4",
851
- "@astryxdesign/cli": "0.7.5-canary.0f3d2f4",
850
+ "@astryxdesign/a11y-spec": "0.7.5-canary.105bbbe",
851
+ "@astryxdesign/cli": "0.7.5-canary.105bbbe",
852
852
  "@babel/cli": "^7.29.7",
853
853
  "@babel/core": "^7.29.7",
854
854
  "@babel/preset-react": "^7.29.7",
@@ -50,7 +50,7 @@ system_specs:
50
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 one new choice, and a row menu is the other: the caller passes a ListItem's ref to `useContextMenu` (FR13), and who draws a plain row's More actions button is open (OQ2); and rows animate only with an `itemKey`; the touch target and press need none. |
51
51
  | 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 (FR10) and the press's compositor release (FR11) are specified, not implemented yet, and change nothing under a fine pointer. Row menus (FR13) are additive and specified, not implemented yet. |
52
52
  | Review checks | Reject header movement, row paint past the host's padding edge, duplicated padding values, physical-edge logic, automatic opt-in, a ListItem-level edge prop, or a second prop that can contradict `edge`. |
53
- | Governing rules | `architecture:container-padding/INV3`, `INV9–INV11`; `spec:AST-002/DEC-1–DEC-2`; `spec:AST-017/FR4`; `spec:AST-057/FR9`. `spec:AST-103`. `spec:AST-094` FR4, FR5, FR11, FR13; `spec:AST-105` FR1–FR5, FR8. `spec:AST-107` FR8 (row menus). |
53
+ | Governing rules | `architecture:container-padding/INV3`, `INV9–INV11`; `spec:AST-002/DEC-1–DEC-2`; `spec:AST-017/FR4`; `spec:AST-057/FR9`. `spec:AST-103`. `spec:AST-094` FR4, FR5, FR11, FR13; `spec:AST-105` FR1–FR5. `spec:AST-107` FR8 (row menus). |
54
54
 
55
55
  This table is a review projection; the body below is authoritative.
56
56
 
@@ -117,21 +117,21 @@ Consumer migration instructions belong in consumer docs and release notes.
117
117
 
118
118
  ## Behavioral and layout contract
119
119
 
120
- | ID | Invariant | Basis | Status |
121
- | ---- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------- |
122
- | FR1 | List MUST own `edge` and apply one treatment to every ListItem row, interactive or not; ListItem MUST NOT expose a parallel public prop. A defined `edge` MUST win over `edgeCompensation`, and `edgeCompensation="inline"` with `edge` undefined MUST resolve to `outset`. | `component:List/DEC-1`, `component:List/DEC-3` | Accepted contract |
123
- | FR2 | `padded` MUST preserve current header, list, and row geometry, apart from FR10's hit target under a coarse pointer. No treatment MAY move the header or change row block padding, gap, markers, start and end content, semantics, or hit target relative to the row box. | Owner direction | Accepted contract |
124
- | FR3 | `flush` MUST resolve each row's inline inset to zero through the private source that supplies Item's applied inline padding, so row content and row paint share the list's inline edges. It reads no host padding. A theme override of row inline padding takes precedence over the zero (FR7). | `component:List/DEC-3` | Accepted contract |
125
- | FR4 | `outset` MUST place each row so it reaches past the host content line by the smaller of its own inline inset and the matching host inset, per logical edge, keeping its inset inside. Content reaches the host line when the host inset is at least the row inset. | `architecture:container-padding/INV9–INV10`; `component:List/DEC-2` | Accepted contract |
126
- | FR5 | `bleed` MUST place each row so it reaches the host's padding edge on each logical edge, with square corners. Row content sits on the host content line, or at the row's own inset from its edge when the host inset is smaller. A theme override of row inline padding sets the content's inset instead (FR7). | `architecture:container-padding/INV3`; `component:List/DEC-4` | Accepted contract |
127
- | FR6 | Missing or reset host inset MUST resolve to zero, so `outset` and `bleed` place content as `padded` does outside a padded host. No row paint MAY reach past the host's padding edge. | `architecture:container-padding/INV6`, `INV9` | Accepted contract |
128
- | FR7 | Each row's retained inset MUST come from the same private density- and theme-derived source as Item's applied inline padding. A theme `item.paddingInline` override takes precedence over every treatment's row padding, as it does over density. A consumer override of row padding through `xstyle`, `className`, or `style` is outside the alignment guarantee. | Shared two-owner geometry contract | Accepted contract |
129
- | 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 |
130
- | 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 |
131
- | 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 |
132
- | 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). The row's dividers stay drawn while it is pressed, in every theme. At rest the row's paint and stacking are as they were. | `spec:AST-094` FR5, FR11 | Accepted contract |
133
- | 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. With a handle, a row also reports a change to its start or end content: content that appears enters, content that leaves exits (a slot that sets the row's height hides at once instead, and the row's other content and the rows after it take their final places at once, as `spec:AST-105`'s Coverage states), content replaced in the same slot swaps in place (`spec:AST-105` FR4, FR8), and the row's other content glides within the row; a slot whose content changes without changing size does not animate. The reorder handle's appearance (`spec:AST-103`) is such a change. A slot control that leaves is inert and hidden from assistive technology as its exit starts; if it held focus, focus moves to the row's focus target (or to the row, which takes focus programmatically for the handoff) without scrolling. | `spec:AST-105` FR1–FR5; `spec:AST-103` DEC-4; `spec:AST-105` FR8; `spec:AST-103` FR2 (the handle renders only with `reorderable`) | Accepted contract |
134
- | FR13 | A row menu on a ListItem attaches to the row's own `<li>`, keeping `ul > li` with no wrapper element: the caller passes the ListItem's ref to `useContextMenu` (`spec:AST-107` FR8), with no ListItem prop of its own; the whole row is its hit area, it opens on the context request (a long press, a right click, or Shift+F10), under a finger, the row takes the press paint (FR11; on a plain row, part of OQ2) and lifts as the menu grows from it, `useContextMenu` lifting the element it is attached to (`spec:AST-094` FR31, FR33), while a mouse, the keyboard, and `presentation: 'popover'` open the released menu without the lift (`spec:AST-094` FR41), and focus returns to the row's focus target when the menu closes. A row that is already focusable (`onClick` or `href`) takes Shift+F10 and the context-menu key directly, and a row with an `interactiveRef` takes them on that element; neither shows a "More actions" button; a row with none of these shows a visible "More actions" button named with the row's label, such as "More actions for Inbox", its keyboard and screen-reader path to the menu. When a menu opens, focus moves into it; when it closes, focus returns to the row's focus target, or to the "More actions" button on a row that shows one. Who moves focus there, since `useContextMenu` returns focus to the `<li>`, which takes none, is part of OQ2. A reorderable row always has its handle (`spec:AST-103` FR3), so when it also has a row menu, a hold on the handle picks the row up and a hold anywhere else on the row opens the menu. | Owner decision, 2026-10-26; `spec:AST-107` FR8 | Accepted contract |
120
+ | ID | Invariant | Basis | Status |
121
+ | ---- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------- | ----------------------------------------------------- |
122
+ | FR1 | List MUST own `edge` and apply one treatment to every ListItem row, interactive or not; ListItem MUST NOT expose a parallel public prop. A defined `edge` MUST win over `edgeCompensation`, and `edgeCompensation="inline"` with `edge` undefined MUST resolve to `outset`. | `component:List/DEC-1`, `component:List/DEC-3` | Accepted contract |
123
+ | FR2 | `padded` MUST preserve current header, list, and row geometry, apart from FR10's hit target under a coarse pointer. No treatment MAY move the header or change row block padding, gap, markers, start and end content, semantics, or hit target relative to the row box. | Owner direction | Accepted contract |
124
+ | FR3 | `flush` MUST resolve each row's inline inset to zero through the private source that supplies Item's applied inline padding, so row content and row paint share the list's inline edges. It reads no host padding. A theme override of row inline padding takes precedence over the zero (FR7). | `component:List/DEC-3` | Accepted contract |
125
+ | FR4 | `outset` MUST place each row so it reaches past the host content line by the smaller of its own inline inset and the matching host inset, per logical edge, keeping its inset inside. Content reaches the host line when the host inset is at least the row inset. | `architecture:container-padding/INV9–INV10`; `component:List/DEC-2` | Accepted contract |
126
+ | FR5 | `bleed` MUST place each row so it reaches the host's padding edge on each logical edge, with square corners. Row content sits on the host content line, or at the row's own inset from its edge when the host inset is smaller. A theme override of row inline padding sets the content's inset instead (FR7). | `architecture:container-padding/INV3`; `component:List/DEC-4` | Accepted contract |
127
+ | FR6 | Missing or reset host inset MUST resolve to zero, so `outset` and `bleed` place content as `padded` does outside a padded host. No row paint MAY reach past the host's padding edge. | `architecture:container-padding/INV6`, `INV9` | Accepted contract |
128
+ | FR7 | Each row's retained inset MUST come from the same private density- and theme-derived source as Item's applied inline padding. A theme `item.paddingInline` override takes precedence over every treatment's row padding, as it does over density. A consumer override of row padding through `xstyle`, `className`, or `style` is outside the alignment guarantee. | Shared two-owner geometry contract | Accepted contract |
129
+ | 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 |
130
+ | 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 |
131
+ | 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 |
132
+ | 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). The row's dividers stay drawn while it is pressed, in every theme. At rest the row's paint and stacking are as they were. | `spec:AST-094` FR5, FR11 | Accepted contract |
133
+ | 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 |
134
+ | FR13 | A row menu on a ListItem attaches to the row's own `<li>`, keeping `ul > li` with no wrapper element: the caller passes the ListItem's ref to `useContextMenu` (`spec:AST-107` FR8), with no ListItem prop of its own; the whole row is its hit area, it opens on the context request (a long press, a right click, or Shift+F10), under a finger, the row takes the press paint (FR11; on a plain row, part of OQ2) and lifts as the menu grows from it, `useContextMenu` lifting the element it is attached to (`spec:AST-094` FR31, FR33), while a mouse, the keyboard, and `presentation: 'popover'` open the released menu without the lift (`spec:AST-094` FR41), and focus returns to the row's focus target when the menu closes. A row that is already focusable (`onClick` or `href`) takes Shift+F10 and the context-menu key directly, and a row with an `interactiveRef` takes them on that element; neither shows a "More actions" button; a row with none of these shows a visible "More actions" button named with the row's label, such as "More actions for Inbox", its keyboard and screen-reader path to the menu. When a menu opens, focus moves into it; when it closes, focus returns to the row's focus target, or to the "More actions" button on a row that shows one. Who moves focus there, since `useContextMenu` returns focus to the `<li>`, which takes none, is part of OQ2. A reorderable row always has its handle (`spec:AST-103` FR3), so when it also has a row menu, a hold on the handle picks the row up and a hold anywhere else on the row opens the menu. | Owner decision, 2026-10-26; `spec:AST-107` FR8 | Accepted contract |
135
135
 
136
136
  ### Allowed variation
137
137
 
@@ -221,17 +221,17 @@ Consumer migration instructions belong in consumer docs and release notes.
221
221
 
222
222
  ## Verification map
223
223
 
224
- | Contract | Verification | Representative states | Mutation or failure expectation | Audit section |
225
- | ------------------------- | ---------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------- |
226
- | FR1–FR7, FR9 | List, Item, and theme-registry tests | every treatment; all densities; static and interactive rows; header; deprecated alias alone and with `edge`; ListItem outside a List | Removing context propagation, using one host edge for both inline edges, zeroing padding without the shared inset source, or dropping the list's reach or clip fails | `audit:List/layout` |
227
- | 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` |
228
- | 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` |
229
- | 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 pressed row between two divided rows | A release that stops while script runs, an element added for the press, a divider hidden during a press, or paint or stacking changed at rest fails | `audit:List/visual` |
230
- | 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 start or end slot gaining, losing, and replacing content, and changing content at the same size; the reorder handle appearing; a focused slot control leaving; a leaving slot that sets the row's height | A staying row that jumps with a handle (other than after a leaving slot that sets the row's height), motion without one, a collapsing removed row that takes focus, pointer input or an accessibility-tree node, a removed row left after its collapse ends, or layout or paint per frame fails. Also fails: a slot change that jumps with a handle (other than a leaving slot that sets the row's height), a same-size slot change that animates, a leaving slot control that keeps focus or stays reachable, a focus move that scrolls, focus that lands on the page body, or a height-setting slot that plays an exit. | `audit:List/visual` |
231
- | Migration | `astryx upgrade` codemod tests | static, aliased, already-migrated, dynamic, and computed-`edge` callsites; a second run | A dynamic value or a computed `edge` rewritten, a static one missed, or a second run that changes output fails | `audit:List/docs` |
232
- | Documentation | `List.doc.mjs`, Storybook, and `scripts/check-knowledge.mjs` | public prop, values, default, deprecation, and representative composition | Missing or stale contract, docs, or example fails | `audit:List/docs` |
233
- | FR13 | List tests and real-browser tests of a row menu with a mouse, a finger, and the keyboard | a plain row, a row with `onClick`, a row with `href`; a right click, a long press, Shift+F10, the context-menu key; close by Escape and by choice; a finger's hold, a mouse's right click, the keyboard, and `presentation: 'popover'` | A wrapper element around the `<li>`, a row a context request does not open, focus left in a closed menu or not returned to the row or its button, a plain row without a named "More actions" button, or a focusable row that ignores Shift+F10 fails. A lift or press paint under a mouse, the keyboard, or `presentation: 'popover'`, or a finger's hold on a focusable row without them, fails. | `audit:List/layout` |
234
- | FR13 reorder | Real-browser tests with a finger and a mouse on a reorderable row with a menu | a hold on the handle and on the row body of a reorderable row with a menu | A handle hold that opens the menu, or a body hold that picks the row up, fails | `audit:List/layout` |
224
+ | Contract | Verification | Representative states | Mutation or failure expectation | Audit section |
225
+ | ------------------------- | ---------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------- |
226
+ | FR1–FR7, FR9 | List, Item, and theme-registry tests | every treatment; all densities; static and interactive rows; header; deprecated alias alone and with `edge`; ListItem outside a List | Removing context propagation, using one host edge for both inline edges, zeroing padding without the shared inset source, or dropping the list's reach or clip fails | `audit:List/layout` |
227
+ | 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` |
228
+ | 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` |
229
+ | 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 pressed row between two divided rows | A release that stops while script runs, an element added for the press, a divider hidden during a press, or paint or stacking changed at rest fails | `audit:List/visual` |
230
+ | 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 collapsing removed row that takes focus, pointer input or an accessibility-tree node, a removed row left after its collapse ends, or layout or paint per frame fails | `audit:List/visual` |
231
+ | Migration | `astryx upgrade` codemod tests | static, aliased, already-migrated, dynamic, and computed-`edge` callsites; a second run | A dynamic value or a computed `edge` rewritten, a static one missed, or a second run that changes output fails | `audit:List/docs` |
232
+ | Documentation | `List.doc.mjs`, Storybook, and `scripts/check-knowledge.mjs` | public prop, values, default, deprecation, and representative composition | Missing or stale contract, docs, or example fails | `audit:List/docs` |
233
+ | FR13 | List tests and real-browser tests of a row menu with a mouse, a finger, and the keyboard | a plain row, a row with `onClick`, a row with `href`; a right click, a long press, Shift+F10, the context-menu key; close by Escape and by choice; a finger's hold, a mouse's right click, the keyboard, and `presentation: 'popover'` | A wrapper element around the `<li>`, a row a context request does not open, focus left in a closed menu or not returned to the row or its button, a plain row without a named "More actions" button, or a focusable row that ignores Shift+F10 fails. A lift or press paint under a mouse, the keyboard, or `presentation: 'popover'`, or a finger's hold on a focusable row without them, fails. | `audit:List/layout` |
234
+ | FR13 reorder | Real-browser tests with a finger and a mouse on a reorderable row with a menu | a hold on the handle and on the row body of a reorderable row with a menu | A handle hold that opens the menu, or a body hold that picks the row up, fails | `audit:List/layout` |
235
235
 
236
236
  ## Decision log
237
237