Every line is a test in three engines or a gate on every commit. The gaps are listed the same way, each with the requirement that will close it.
GapARIA APG pattern in the JSDocnone — gap
n/aKeyboard mapnot applicable — native
MeasuredNo aria-checked of its ownlibs/components/checkbox/src/checkbox.spec.ts › never writes aria-checked — the absence in all three states; apps/sandbox-e2e/src/checkbox.spec.ts — the accessible tree read in three engines, [checked] from the checkedness and [checked=mixed] from the indeterminate property alone (0039, lesson-112) Measuredaxe auditapps/sandbox-e2e/src/a11y.spec.ts — including a separate test of the indeterminate state
MeasuredVisual screenshotapps/sandbox-e2e/src/visual.spec.ts
Measuredforced-colors: activeapps/sandbox-e2e/src/forced-colors.spec.ts — the tick toggles visibility, so the state is carried by the presence of a shape, not by colour (lesson-40); tools/check-styles.mjs (point 7) found the disabled box keeping a theme surface instead of Field (lesson-70) Measuredprefers-reduced-motionapps/sandbox-e2e/src/preferences.spec.ts
MeasuredTouch target ≥ 24×24 pxapps/sandbox-e2e/src/checkbox.spec.ts — the box is 18 px, the hit zone is enlarged and centred; met outright, not through the spacing exception (lesson-14) n/aSize axisnot applicable — the bare variant does not align heights (0004) GapDensity axisnone — gap. Elevated risk: density will drop below the touch threshold sooner than size sm
MeasuredRTLtools/check-styles.mjs (point 5, req-token-logical) over the stylesheet — one justified pct-exception, the symmetric left: 50% of the hit zone, where inset-inline-start would be a defect and not an improvement — plus the checkbox-in-wrapper-rtl baseline in apps/sandbox-e2e/src/visual.spec.ts MeasuredSSR + hydrationapps/sandbox-e2e/src/hydration.spec.ts
MeasuredFormslibs/components/checkbox/src/checkbox.spec.ts, apps/sandbox-e2e/src/forms.spec.ts; a form's reset — reset() keeping the value, reset(value) showing it, the form pristine: libs/components/checkbox/src/checkbox.spec.ts › signal forms
MeasuredThe mark through PCT_ICONStools/check-icons.mjs (target check-icons), libs/components/checkbox/src/checkbox.spec.ts — check and indeterminate are two names, and a set carrying one of them leaves the other to the component
MeasuredParts in the inventorylibs/components/parts.snapshot.md, tools/check-parts.mjs (target check-parts). Note: the control part collided with the native input once wrapped (lesson-24) MeasuredTokens + contrast.policy.jsonlibs/tokens/src/contrast.policy.json
MeasuredStrings through PCT_TEXTStools/check-texts.mjs — no strings of its own
MeasuredSize budgetlibs/components/size.snapshot.md — the ./checkbox row
MeasuredScreen-reader logRead 2026-10-12 from docs/acr/at/ — three readers, whole sandbox. mixed is announced by every reader that reaches it: NVDA The indeterminate state, read as mixed, check box, half checked; VoiceOver reached it in the pass of 2026-10-08 (dd0f02fa) — The indeterminate state, read as mixed mixed checkbox, and the read-only box Read-only — focusable, but not changeable checked checkbox — and left this view after one stop on 2026-09-28 and on 2026-10-12. Orca never reaches it — its walk ends after one stop, focus leaving main for the scaffold — and its one reading is the required box, Consents · check box not checked required. · invalid entry. · Required to open an account., which VoiceOver read whole on 2026-10-12, Consents Required to open an account required invalid data unchecked checkbox, where on 2026-10-08 it said only the message. The READ-ONLY box is check box, checked to NVDA: the words read-only reach it in the label and the state does not, although aria-readonly is on the control — an attribute the reader does not say
Measureddocs page/components/checkbox on the published site — prerendered, the demo's own source is the code tab