Skip to content

[test][FormControlLabel] Add axe tests and WCAG conformance report - #49524

Open
rohits2501 wants to merge 6 commits into
mui:masterfrom
rohits2501:test/form-control-label-a11y
Open

rohits2501 wants to merge 6 commits into
mui:masterfrom
rohits2501:test/form-control-label-a11y

Conversation

@rohits2501

@rohits2501 rohits2501 commented Oct 21, 2026 •

Copy link
Copy Markdown
Contributor

Closes #49409

Adds a WCAG 2.2 (Level A/AA) conformance assessment for FormControlLabel, following the existing component reports. This is an assessment only. No component or theme behavior changes.

Scope decision

FormControlLabel wraps a Checkbox, Radio, or Switch, so it has no single parent to inherit from. The report rates the 14 criteria the label's own text, placement, and association are responsible for, and marks the wrapped control's keyboard, focus, pointer, role, and value behavior Not Applicable, since those are rated in the control reports.

What's included

  • FormControlLabel/accessibility.json (the source of truth) and the generated accessibility.md.
  • A dedicated form-control-label docs slug and axe fixture FormControlLabelA11yStates, enrolled in demoMeta.ts with a matching demoMeta.test.ts case, so axe results stay out of the Checkbox, Radio, and Switch slugs.
  • A CSS_LAYOUT_SUITES entry with all three layout criteria (1.4.4, 1.4.10, 1.4.12) applying, since the label renders text. It is not added to FOCUS_VISIBLE_TARGETS because the label is not focusable.
  • Unit tests for the label-owned behavior: the accessible name for all three controls, the required asterisk excluded from the name, label-click toggling the control, and DOM order kept before the label for every labelPlacement.

Findings (the checks in the issue)

  • 1.3.1, 4.1.2 Info and Relationships / Name, Role, Value: Supports. The <label> root clones the control inside it, so the control's accessible name comes from the visible label text.
  • 2.5.3 Label in Name: Supports. With a string label the accessible name equals the visible text; the decorative required asterisk is excluded.
  • 2.5.8 Target Size (Minimum): Supports. The whole label is the activation target, enlarging the control's hit area. axe-core target-size passes.
  • 1.3.2 Meaningful Sequence: Supports. The control always precedes the label in the DOM; labelPlacement changes only the visual order.
  • 3.3.2 Labels or Instructions: Supports. The control gets a visible label, and required shows a visible asterisk with the native required state.
  • 1.4.3 Contrast (Minimum): Supports. The label inherits text.primary and the disabled label (text.disabled) is exempt. axe-core color-contrast passes.

No partials or gaps were found, so there is no follow-up fix PR for this component.

Notes

  • Manual checks used Chrome's accessibility tree and computed colors. A screen-reader pass (NVDA/VoiceOver) has not been done yet; the report marks the assistive-technology review as still open, matching the other component reports.
  • form-control-label.a11y.json is generated by the regression harness (pnpm test:regressions), not hand-written.

@rohits2501
rohits2501 force-pushed the test/form-control-label-a11y branch from b12a769 to 937d877 Compare October 21, 2026 17:26
@code-infra-dashboard

code-infra-dashboard Bot commented Oct 21, 2026 •

Copy link
Copy Markdown

Deploy preview

Bundle size

Bundle Parsed size Gzip size
@mui/material 0B(0.00%) 0B(0.00%)
@mui/lab 0B(0.00%) 0B(0.00%)
@mui/private-theming 0B(0.00%) 0B(0.00%)
@mui/system 0B(0.00%) 0B(0.00%)
@mui/utils 0B(0.00%) 0B(0.00%)

Details of bundle changes

Performance

No regressions in 32 benchmarks · ran 4m 19s · details


Check out the code infra dashboard for more information about this PR.

@rohits2501
rohits2501 force-pushed the test/form-control-label-a11y branch from 937d877 to 2bfd08c Compare October 21, 2026 17:32
@rohits2501

Copy link
Copy Markdown
Contributor Author

Hi @JCQuintas @silviuaavram, could you take a look when you get a chance?
This is the WCAG 2.2 assessment for FormControlLabel (#49409).
No component behavior changes.
CI is green.

@michelengelen

Copy link
Copy Markdown
Member

Hey @rohits2501 👋 While reviewing the other Form* reports from Wave 1 (FormLabel #49552, FormHelperText #49553, FormGroup #49554), we noticed the four reports rated the same criteria in different ways. We aligned them on a small set of rules, most of which come straight from the merged reports:

  1. Rate a criterion only if the component renders the content, semantics, layout, or behavior it covers; otherwise N/A (the VPAT definition, and how Progress/Avatar already do it).
  2. Text criteria (1.4.3, 1.4.4, 1.4.12) only apply if the component renders text of its own.
  3. 4.1.2 / 2.5.3 only apply if the component sets a role or its own markup supplies a control's name.
  4. 3.2.4 is N/A for non-interactive parts (each control's report already rates it).
  5. Responsibility is Component when the component sets the value itself (for example, its own text color).
  6. A decorative glyph that duplicates a native state does not trigger 1.1.1 (the TextField precedent). If it conveys something that is not exposed, that's a 1.3.1 issue instead.
  7. One root cause gets one ⚠️, on the component that creates it; the other reports link to it.
  8. A test only counts as evidence if it would fail when the component's own output regresses.

Your report already lines up with almost all of this (3.2.4 N/A, 2.5.8 Shared, and 2.5.3/4.1.2 rated because the <label> supplies the name 👍). Three small things would make it fully consistent:

  • 1.1.1: FormControlLabel forwards required to the control (your 4.1.2 test proves it), so the asterisk only duplicates a native state. Under rule 6 that makes 1.1.1 Not Applicable, with the same reason TextField uses ("decorative aria-hidden text that duplicates the native required state").
  • 1.3.1: the region says "Confirmed by a unit test", but no test title starts with 1.3.1 Info and Relationships, so the report shows no unit evidence for it. Either retitle the "label wraps the control" test (for example 1.3.1 Info and Relationships: associates the control with its label by wrapping it), or drop that sentence.
  • 1.3.2 (optional): labelPlacement applies the row-reverse / column-reverse / column layout itself, so by rule 5 this could be ◐ Shared instead of ○ Author.

The required state of a group (a required FormLabel legend over checkboxes or radios, where the controls never get required) is rated once, as a 1.3.1 gap on FormLabel in #49552. A one-line link to it from your 1.3.1 notes would be nice, but it isn't required.

Happy to help with any of this if you'd like!

Rate 1.1.1 not applicable, since the required asterisk only duplicates the native required state. Rate 1.3.2 as shared, since labelPlacement sets the layout. Add the 1.3.1 unit test the report cites.
@rohits2501

Copy link
Copy Markdown
Contributor Author

Thanks @michelengelen, all three are in 0dceb0d.

  • 1.1.1: now Not Applicable, with the TextField reason: the required * is decorative (aria-hidden) text duplicating the native required state it forwards to the control.
  • 1.3.1: added 1.3.1 Info and Relationships: associates the control with its label by wrapping it, so the report now shows unit evidence for it.
  • 1.3.2: now Shared, since labelPlacement sets the layout itself.

I left out the FormLabel link for now because #49552 has not merged, so the relative link would point to a missing file. I can add it once that lands.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

component: FormControl The React component. test

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[a11y][FormControlLabel] Assess WCAG 2.2 conformance

3 participants