milestone 23 s2: react aria primitives and their cluster
This commit is contained in:
@@ -347,6 +347,121 @@ Tailwind dependency pair and its vite plugin line and CSS import.
|
||||
- [ ] `web/src/lib/types.ts` and `web/src/lib/contractSamples.gen.ts` are
|
||||
byte-identical to HEAD.
|
||||
|
||||
## Recorded (implementation)
|
||||
|
||||
Written during S1 and the S2 hand-off. Each entry is a place the spec was wrong
|
||||
or a decision the spec did not have.
|
||||
|
||||
### S1 could not put StyleX in the bundle, and its acceptance says otherwise
|
||||
|
||||
S1 owns no page file, so no production module imports StyleX and rollup emits
|
||||
none of it. Two S1 boxes — "`npm run build` emits StyleX CSS into the `web/dist`
|
||||
assets" and "`assert-bundled` passes with `@stylexjs/stylex` in the recorded
|
||||
set" — are therefore unmeetable inside S1 as scoped, and the recorded bundled
|
||||
set is unchanged at the S1 commit. Both were proven instead against a temporary
|
||||
probe component, then deferred to S2, which converts real pages and does change
|
||||
the bundled set. Ruling 8's "S1 adds `@stylexjs/stylex` ... to the runtime
|
||||
closure and the bundled set" is half right: the closure moves in S1, the bundled
|
||||
set in S2. The inventory entry for StyleX is anticipatory at the S1 commit,
|
||||
which is deliberate — see the styleq entry for why it cannot wait.
|
||||
|
||||
### The probe results, recorded rather than left as a claim
|
||||
|
||||
Against the temporary probe: the built CSS carries `@layer priority1..N` and the
|
||||
token variables, resolving to `#fafafa` light and `#09090b` dark with
|
||||
lightningcss `lab()` fallbacks. The dev server needs no wiring of its own — the
|
||||
plugin injects `<link rel="stylesheet" href="/virtual:stylex.css">` into
|
||||
`index.html`, so the `DevStyleXInject` component in StyleX's Vite guide is for
|
||||
frameworks that bypass Vite's HTML transform and is not used here. Editing a
|
||||
token regenerates the virtual stylesheet and the dev server issues a page
|
||||
reload.
|
||||
|
||||
### S1 wrote outside its owned files, and outside an anti-requirement
|
||||
|
||||
The licence guard forced it: `licenses/stylex-mit.txt`, `licenses/styleq-mit.txt`
|
||||
and their registration in `licenses/licenses.zig`, plus the `npm_not_shipped`
|
||||
array in `src/licenses_drift_test.zig`. The last contradicts the "no edits ...
|
||||
under `src/`" anti-requirement below. The anti-requirement is amended, not
|
||||
ignored: `src/licenses_drift_test.zig` is writable for its licence-fact arrays
|
||||
and, from S2, for the per-package licence change described next. The rest of
|
||||
`src/` stays closed.
|
||||
|
||||
### Apache-2.0 inbound: a decision, not a deduction
|
||||
|
||||
`react-aria-components` 1.20.0 brings eight Apache-2.0 packages
|
||||
(react-aria-components, react-aria, react-stately, `@react-types/shared`, three
|
||||
`@internationalized/*`, `@swc/helpers`) and `tslib` under 0BSD into an EUPL-1.2
|
||||
project. The user accepted Apache-2.0 inbound on 2026-08-12 and authorised the
|
||||
guard change it needs. This is recorded as their decision because nothing in the
|
||||
licence settles it: EUPL-1.2's appendix does not list Apache-2.0 — it names GPL,
|
||||
AGPL, OSL, EPL, CeCILL, MPL, LGPL, CC BY-SA, EUPL and LiLiQ — and that appendix
|
||||
governs Article 5 outbound relicensing, not inbound consumption. Any claim that
|
||||
the appendix permits this is false and must not be written into the inventory.
|
||||
`src/licenses_drift_test.zig:122` hardcodes a single expected licence and
|
||||
becomes per-package in S2; the guard stays strict, an unexpected licence still
|
||||
fails.
|
||||
|
||||
### Ruling 8's picture of the React Aria closure is wrong
|
||||
|
||||
There are no `@react-aria/*` or `@react-stately/*` scoped packages. RAC 1.20.0
|
||||
ships consolidated `react-aria` and `react-stately`. The runtime closure it adds
|
||||
is the eleven packages named above plus `aria-hidden`, `clsx` and `client-only`
|
||||
under MIT — not the "dozens" the ruling anticipated.
|
||||
|
||||
### Ruling 11's claim about the tab tests is wrong
|
||||
|
||||
`LocalDnsPage.tsx` already renders `role="tablist"` and `role="tab"` by hand, so
|
||||
no test query moves from `getByRole("button")` to `getByRole("tab")`. What RAC
|
||||
adds there is keyboard arrow-key navigation, which the hand-rolled switcher
|
||||
lacks, and that is what the S2 acceptance box asserts.
|
||||
|
||||
### `formCard` is a layout change, not a port
|
||||
|
||||
`space-y-3` set sibling margins on a block container; the StyleX version is a
|
||||
flex column with `gap`. StyleX cannot express the `> * + *` selector `space-y`
|
||||
compiles to, so `gap` is the only mechanism available. Both call sites
|
||||
(`RecordsTab`, `ZonesTab`) are plain vertical form stacks, where the difference
|
||||
in child sizing and margin behaviour does not show. Recorded against ruling 7,
|
||||
which pins layout structure.
|
||||
|
||||
### S2 needed two build-config changes the spec did not anticipate
|
||||
|
||||
Both are in files S1 and S3 own, both were forced, and neither is optional.
|
||||
|
||||
`web/vitest.setup.ts` (new) plus `setupFiles` in `web/vite.config.ts`: jsdom
|
||||
implements no `CSS` interface at all, and React Aria's collection code calls
|
||||
`CSS.escape` unguarded when it looks an item up by key
|
||||
(`react-aria/dist/private/selection/utils.mjs:22`). Every RAC Select and Tabs
|
||||
test threw `Cannot read properties of undefined (reading 'escape')` before this
|
||||
landed. The setup file implements CSSOM's *serialize an identifier* algorithm
|
||||
rather than approximating it, because a wrong escape would break the key lookups
|
||||
silently instead of loudly.
|
||||
|
||||
The `@` alias passed to `stylex.vite()` in `web/vite.config.ts`: StyleX resolves
|
||||
the `.stylex.ts` theme file itself and cannot see Vite's `resolve.alias`, so
|
||||
`import { colors } from "@/ui/tokens.stylex"` in a feature file failed the build
|
||||
with "Could not resolve the path to the imported file". Relative imports were the
|
||||
alternative; passing the alias keeps the repo's `@/` convention instead.
|
||||
|
||||
### RAC Select changes the accessible name of a labelled control
|
||||
|
||||
`useSelect` labels the trigger button with `aria-labelledby="<value> <label>"`,
|
||||
so a select labelled "Type" showing "A" has the accessible name "A Type", and
|
||||
`getByLabelText("Type")` no longer finds it. Converted tests query
|
||||
`getByRole("button", { name: /Type$/ })` and read the options by opening the
|
||||
listbox. RAC also renders a hidden native `<select>` for form submission; it sits
|
||||
inside an `aria-hidden` container, so role and label queries skip it.
|
||||
|
||||
### Two notes for S3
|
||||
|
||||
`textMuted` resolves to zinc-400 in dark mode. Several current `text-zinc-500`
|
||||
call sites carry no dark override and stay zinc-500, so the token cannot replace
|
||||
those without a shade shift — decide per call site rather than sweeping.
|
||||
|
||||
Vitest began reporting "Tests closed successfully but something prevents Vite
|
||||
server from exiting" with the StyleX plugin in the pipeline. The suite passes
|
||||
and exits 0. It should not be allowed to become the accepted baseline.
|
||||
|
||||
## Anti-requirements
|
||||
|
||||
- No router or query changes: TanStack Router and TanStack Query stay,
|
||||
|
||||
Reference in New Issue
Block a user