Skip to content

Document how upstream and Radix test, and how both solve form participation - #2

Merged
MentalGear merged 1 commit into
mainfrom
claude/fork-fix-mining-ajwum2
Aug 29, 2026
Merged

MentalGear merged 1 commit into
mainfrom
claude/fork-fix-mining-ajwum2

Conversation

@MentalGear

Copy link
Copy Markdown
Owner

Follow-up research to PR #1, answering two questions with measurement rather than assumption. Documentation only.

How the existing suites are built — and where they stop

This project splits work sensibly: cargo unit tests cover the algorithmic modules (10 of 40 files in primitives/srcslider, calendar, virtualizer, text_search, pointer, …), while 32 Playwright specs with 122 tests cover interaction in a real browser. CI runs check/test/fmt/docs/clippy with warnings denied. There is no component-level DOM/ARIA unit test because Rust has no jsdom equivalent — which is what hovinen's dioxus-test branch was exploring.

Where the e2e suite stops is precise:

Assertion Count
keyboard.press 167
toBeFocused 84
axe scans 3 specs of 32
aria-hidden 0
overflow / scrollY 0

It tests what a component does, never what it must prevent — and never where focus lands after a close, only that the thing closed. That is the exact shape of the gaps recorded in capability-gaps.md, and why they survived 122 tests.

Radix uses vitest + @testing-library/react + vitest-axe, with large suites (select.test.tsx 1,610 lines, radio-group 983, checkbox 829). But FormData appears zero times across their checkbox, radio-group and select tests: they assert the bubble input renders with type="radio" and aria-hidden, never that submitting a form produces the entry.

So the entry-list rules proposed in conformance-harness.md exceed what the reference implementation tests. Useful in both directions — the proposal isn't redundant, and it can't lean on Radix's precedent either. It stands on the HTML spec, which is enough.

How div role="radio" is made to submit

It can't be, directly — HTML restricts the entry list to submittable elements, and ARIA changes what an element is announced as, never what it submits as. Since Dioxus renders plain DOM rather than custom elements, ElementInternals.setFormValue() is also unavailable. A real submittable element has to exist.

Both references do that:

  • Radix renders the hidden input conditionallyisFormControl = control ? !!form || !!control.closest('form') : true (defaulting true so SSR still bubbles) — then emits <input type="radio" aria-hidden tabIndex={-1} name value required disabled form> beside the visual button.
  • This repo's Checkbox does the same thing unconditionally (checkbox.rs:279-296): a real <input type="checkbox"> with aria_hidden, tabindex="-1", hidden by inline style, synced via document::eval.

The pattern is therefore already in this codebase — applied to Checkbox and Switch, never extended to RadioGroup or Select. Fixing them applies the project's own existing solution rather than introducing new design, which is also the strongest framing for an upstream PR. The only real choice is whether to match Radix's conditional rendering or Checkbox's unconditional one; either is defensible, a third invention is not.


Generated by Claude Code

…ticipation

Two questions answered with evidence rather than assumption.

How the suites are built. This project splits work sensibly: cargo unit
tests cover the algorithmic modules (10 of 40 files in primitives/src --
slider, calendar, virtualizer, text_search, pointer, and so on) while 32
Playwright specs with 122 tests cover interaction in a real browser, and
CI runs check/test/fmt/docs/clippy with warnings denied. There is no
component-level DOM/ARIA unit test because Rust has no jsdom equivalent,
which is what hovinen's dioxus-test branch was exploring.

Where that suite stops is the revealing part: 167 keyboard.press and 84
toBeFocused assertions, but zero for aria-hidden and zero for
overflow/scrollY, and axe in only 3 specs of 32. It tests what a
component does and never what it must prevent -- the exact shape of the
gaps recorded in capability-gaps.md.

Radix uses vitest with testing-library and vitest-axe, with large suites
(select 1610 lines, radio-group 983, checkbox 829). But FormData appears
zero times in their checkbox, radio-group and select tests: they assert
the bubble input renders with type=radio and aria-hidden, never that
submitting a form produces the entry. The entry-list rules proposed here
therefore exceed what the reference implementation tests, and must stand
on the HTML spec rather than on Radix's precedent.

How the div-role=radio problem is solved. Radix renders a real hidden
input conditionally, gated on control.closest('form'), defaulting true
for SSR. This repo's Checkbox does the same thing unconditionally at
checkbox.rs:279-296, hidden via inline style and synced through
document::eval. The pattern is therefore already in this codebase and
was simply never extended to RadioGroup or Select, which makes fixing
them an application of the project's own existing solution rather than
new design.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01K3xAwYCh5jJupi9U4CG5C7
@MentalGear
MentalGear merged commit 10f1c62 into main Aug 29, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants