diff --git a/docs/data/material/components/form-group/form-group.a11y.json b/docs/data/material/components/form-group/form-group.a11y.json new file mode 100644 index 00000000000000..ed7555b1c5cbca --- /dev/null +++ b/docs/data/material/components/form-group/form-group.a11y.json @@ -0,0 +1,66 @@ +{ + "FormGroupA11yStates": { + "rules": { + "aria-allowed-attr": { + "status": "pass", + "tags": ["wcag2a"] + }, + "aria-conditional-attr": { + "status": "pass", + "tags": ["wcag2a"] + }, + "aria-deprecated-role": { + "status": "pass", + "tags": ["wcag2a"] + }, + "aria-hidden-focus": { + "status": "pass", + "tags": ["wcag2a"] + }, + "aria-prohibited-attr": { + "status": "pass", + "tags": ["wcag2a"] + }, + "aria-required-attr": { + "status": "pass", + "tags": ["wcag2a"] + }, + "aria-roles": { + "status": "pass", + "tags": ["wcag2a"] + }, + "aria-valid-attr": { + "status": "pass", + "tags": ["wcag2a"] + }, + "aria-valid-attr-value": { + "status": "pass", + "tags": ["wcag2a"] + }, + "color-contrast": { + "status": "pass", + "tags": ["wcag2aa"] + }, + "duplicate-id-aria": { + "status": "pass", + "tags": ["wcag2a"] + }, + "form-field-multiple-labels": { + "status": "pass", + "tags": ["wcag2a"] + }, + "label": { + "status": "pass", + "tags": ["wcag2a"] + }, + "nested-interactive": { + "status": "pass", + "tags": ["wcag2a"] + }, + "target-size": { + "status": "pass", + "tags": ["wcag22aa"] + } + } + } +} diff --git a/docs/data/material/getting-started/accessibility/accessibility.md b/docs/data/material/getting-started/accessibility/accessibility.md index ca08a4cef34293..55adfa3619dd48 100644 --- a/docs/data/material/getting-started/accessibility/accessibility.md +++ b/docs/data/material/getting-started/accessibility/accessibility.md @@ -3,7 +3,7 @@

How Material UI components conform to WCAG 2.2 Level A and AA, reported in VPAT terms for procurement and accessibility review.

:::warning -**Draft — partial coverage.** This report covers the 13 components assessed so far, not the whole library. It has not been reviewed by an external auditor, and no assistive-technology testing has been performed yet. See [Scope and limitations](#scope-and-limitations) before relying on it for a procurement decision. +**Draft — partial coverage.** This report covers only the components in the [component table](#conformance-by-component), not the whole library. It has not been reviewed by an external auditor, and no assistive-technology testing has been performed yet. See [Scope and limitations](#scope-and-limitations) before relying on it for a procurement decision. ::: ## About this report @@ -43,6 +43,7 @@ Each row counts only the criteria that **apply** to that component; criteria tha | [Button](https://github.com/mui/material-ui/blob/master/packages/mui-material/src/Button/accessibility.md) | 15 | 12 | 27 | 24 | 3 | 20/27 | 11 | | [Checkbox](https://github.com/mui/material-ui/blob/master/packages/mui-material/src/Checkbox/accessibility.md) | 14 | 11 | 25 | 24 | 1 | 22/25 | 11 | | [CircularProgress](https://github.com/mui/material-ui/blob/master/packages/mui-material/src/CircularProgress/accessibility.md) | 6 | 5 | 11 | 8 | 3 | 6/11 | 1 | +| [FormGroup](https://github.com/mui/material-ui/blob/master/packages/mui-material/src/FormGroup/accessibility.md) | 5 | 2 | 7 | 7 | 0 | 4/7 | 2 | | [LinearProgress](https://github.com/mui/material-ui/blob/master/packages/mui-material/src/LinearProgress/accessibility.md) | 6 | 5 | 11 | 8 | 3 | 6/11 | 1 | | [Radio](https://github.com/mui/material-ui/blob/master/packages/mui-material/src/Radio/accessibility.md) | 14 | 11 | 25 | 24 | 1 | 23/25 | 11 | | [RadioGroup](https://github.com/mui/material-ui/blob/master/packages/mui-material/src/RadioGroup/accessibility.md) | 6 | 1 | 7 | 7 | 0 | 4/7 | 2 | @@ -106,7 +107,7 @@ const theme = createTheme({ focusVisible: true }); Read this section before citing the report. ::: -- **Component coverage is partial.** 13 components are assessed. Widely used components including Select, Autocomplete, Dialog, Menu, Table, Tabs, Slider, Tooltip, Snackbar, and Drawer are **not yet assessed**, and this report says nothing about them. +- **Component coverage is partial.** Only the components in the [component table](#conformance-by-component) are assessed. Widely used components including Select, Autocomplete, Dialog, Menu, Table, Tabs, Slider, Tooltip, Snackbar, and Drawer are **not yet assessed**, and this report says nothing about them. - **No assistive-technology testing.** No screen-reader passes have been performed. Criteria that depend on how a specific assistive technology behaves are assessed from the exposed accessibility tree, not from observed behavior. - **Level AAA is out of scope**, as it is for a standard VPAT. - **Components are rated in isolation**, as rendered with default props and the default theme. Customization, composition, and your surrounding page can change the result. diff --git a/docs/data/material/getting-started/accessibility/scorecard.json b/docs/data/material/getting-started/accessibility/scorecard.json index 5602791ebcc2b5..dd6d376c0d4383 100644 --- a/docs/data/material/getting-started/accessibility/scorecard.json +++ b/docs/data/material/getting-started/accessibility/scorecard.json @@ -1,6 +1,6 @@ { "standard": "WCAG 2.2 Level A and AA", - "componentCount": 13, + "componentCount": 14, "totals": { "rated": 32, "supports": 27, @@ -1538,6 +1538,93 @@ "automated": 1 } }, + { + "component": "FormGroup", + "counts": { + "supports": 7, + "partiallySupports": 0, + "doesNotSupport": 0, + "notApplicable": 48, + "flagged": 3, + "rated": 7 + }, + "gaps": [], + "criteria": [ + { + "number": "1.3.1", + "name": "Info and Relationships", + "level": "A", + "conformance": "Supports", + "responsibility": "Shared", + "group": "Hybrid", + "flagged": false + }, + { + "number": "1.3.2", + "name": "Meaningful Sequence", + "level": "A", + "conformance": "Supports", + "responsibility": "Shared", + "group": "Manual", + "flagged": true + }, + { + "number": "1.3.3", + "name": "Sensory Characteristics", + "level": "A", + "conformance": "Supports", + "responsibility": "Author", + "group": "Manual", + "flagged": false + }, + { + "number": "1.4.10", + "name": "Reflow", + "level": "AA", + "conformance": "Supports", + "responsibility": "Shared", + "group": "Automated", + "flagged": false + }, + { + "number": "2.4.3", + "name": "Focus Order", + "level": "A", + "conformance": "Supports", + "responsibility": "Shared", + "group": "Automated", + "flagged": false + }, + { + "number": "2.4.6", + "name": "Headings and Labels", + "level": "AA", + "conformance": "Supports", + "responsibility": "Shared", + "group": "Manual", + "flagged": true + }, + { + "number": "3.3.2", + "name": "Labels or Instructions", + "level": "A", + "conformance": "Supports", + "responsibility": "Shared", + "group": "Hybrid", + "flagged": true + } + ], + "summary": { + "rated": 7, + "levelA": 5, + "levelAA": 2, + "supports": 7, + "partiallySupports": 0, + "doesNotSupport": 0, + "verified": 4, + "automated": 2 + } + }, { "component": "LinearProgress", "counts": { diff --git a/packages/mui-material/src/FormGroup/FormGroup.test.js b/packages/mui-material/src/FormGroup/FormGroup.test.js index a33b21f2b3a6ab..b3e67b1f6c2f15 100644 --- a/packages/mui-material/src/FormGroup/FormGroup.test.js +++ b/packages/mui-material/src/FormGroup/FormGroup.test.js @@ -1,7 +1,9 @@ import { describe, it, expect } from 'vitest'; -import { createRenderer, screen } from '@mui/internal-test-utils'; +import * as React from 'react'; +import { createRenderer, screen, within, isJsdom } from '@mui/internal-test-utils'; import FormGroup, { formGroupClasses as classes } from '@mui/material/FormGroup'; import FormControl from '@mui/material/FormControl'; +import FormLabel from '@mui/material/FormLabel'; import describeConformance from '../../test/describeConformance'; describe('', () => { @@ -42,4 +44,87 @@ describe('', () => { }); }); }); + + describe('accessibility', () => { + it('renders no role of its own', () => { + const { container } = render( + + + , + ); + + expect(container.firstChild).not.to.have.attribute('role'); + expect(screen.queryByRole('group')).to.equal(null); + }); + + it('gets its group name from a fieldset legend', () => { + render( + + Toppings + + + + , + ); + + const group = screen.getByRole('group', { name: 'Toppings' }); + expect(within(group).getByRole('checkbox', { name: 'Cheese' })).not.to.equal(null); + }); + + it('makes the controls of a row group tab stops in DOM order', async () => { + const { user } = render( + + + + + , + ); + + for (const name of ['Email', 'Push', 'Text message']) { + // eslint-disable-next-line no-await-in-loop + await user.tab(); + expect(screen.getByRole('checkbox', { name })).toHaveFocus(); + } + }); + }); + + describe('WCAG 2.2 conformance', () => { + it('1.3.1 Info and Relationships: becomes a named group with role="group" and aria-labelledby', () => { + render( + + Share with + + + + , + ); + + expect(screen.getByRole('group')).toHaveAccessibleName('Share with'); + }); + + // JSDOM has no layout + it.skipIf(isJsdom())( + '2.4.3 Focus Order: a row group shows its controls from left to right in tab order', + async () => { + const { user } = render( + + + + + , + ); + + let previousLeft = -Infinity; + for (const name of ['Email', 'Push', 'Text message']) { + // eslint-disable-next-line no-await-in-loop + await user.tab(); + const checkbox = screen.getByRole('checkbox', { name }); + expect(checkbox).toHaveFocus(); + const { left } = checkbox.getBoundingClientRect(); + expect(left).to.be.above(previousLeft); + previousLeft = left; + } + }, + ); + }); }); diff --git a/packages/mui-material/src/FormGroup/accessibility.json b/packages/mui-material/src/FormGroup/accessibility.json new file mode 100644 index 00000000000000..dc3bd0ee456ddd --- /dev/null +++ b/packages/mui-material/src/FormGroup/accessibility.json @@ -0,0 +1,28 @@ +{ + "axe": "docs/data/material/components/form-group/form-group.a11y.json", + "criteria": { + "1.3.2": { "responsibility": "Shared", "flagged": true }, + "2.4.6": { "group": "Manual", "flagged": true }, + "3.3.2": { "flagged": true } + }, + "notApplicable": [ + "1.1.1", + "1.4.1", + "1.4.3", + "1.4.4", + "1.4.5", + "1.4.11", + "1.4.12", + "2.1.1", + "2.1.2", + "2.4.7", + "2.4.11", + "2.5.2", + "2.5.3", + "2.5.8", + "3.2.1", + "3.2.2", + "3.2.4", + "4.1.2" + ] +} diff --git a/packages/mui-material/src/FormGroup/accessibility.md b/packages/mui-material/src/FormGroup/accessibility.md new file mode 100644 index 00000000000000..2efb2bf5bf8ea5 --- /dev/null +++ b/packages/mui-material/src/FormGroup/accessibility.md @@ -0,0 +1,212 @@ + + +# FormGroup accessibility conformance + +Rated against WCAG 2.2 Level A and AA. See the [reports legend](../accessibility.md). + + + +FormGroup arranges a set of checkboxes or switches. It renders a `div` with no role. The group semantics come from a `fieldset` with a legend, or from `role="group"` with a name. For radio buttons, use RadioGroup. + +FormGroup rates layout criteria (1.3.2, 1.4.10, 2.4.3) because it sets the layout, and group criteria (1.3.1, 2.4.6, 3.3.2) because `role="group"` makes it the named group element. + + + +| Result | Count | +| :-------------------- | :---- | +| ✅ Supports | 7 | +| ⚠️ Partially Supports | 0 | +| ❌ Does Not Support | 0 | +| ➖ Not Applicable | 48 | +| 🚩 Flagged | 3/7 | + +## Known gaps + +None. + +## Success criteria + +### 🔍 Manual + +#### 1.3.2 Meaningful Sequence · A + +`🚩` · `✅ Supports` · `◐ Shared` + + + +- FormGroup shows its controls in DOM order, in a column, or in a row with `row`. It does not reverse the order. + +**Manual testing steps** + +1. Start a screen reader. +2. Read a FormGroup with `row` with the reading keys (Down Arrow in NVDA, VO+Right Arrow in VoiceOver). +3. Compare the reading order with the visual order. + + + +**Pass:** the reading order matches the visual order. + +#### 1.3.3 Sensory Characteristics · A + +`✅ Supports` · `○ Author` + + + +- Instructions for a group must not rely on its position or color alone. This is an authoring concern. + +**Manual testing steps** + +1. Find product copy that refers to a group of options. +2. Make sure that it names the group by its label. + + + +**Pass:** each instruction names the group by its label. + +#### 2.4.6 Headings and Labels · AA + +`🚩` · `✅ Supports` · `◐ Shared` + + + +- The legend or the `aria-labelledby` element names the group. Whether the name describes the group is an authoring concern. + +**Manual testing steps** + +1. List the name of each group. +2. Read each name without its options. + + + +**Pass:** each group name tells the purpose of the set, for example "Toppings". + +### 🔁 Hybrid + +#### 1.3.1 Info and Relationships · A + +`✅ Supports` · `◐ Shared` + +Tested by: unit `FormGroup.test.js` + + + +- FormGroup renders a `div` with no role, so by itself it does not tell assistive technology that the controls form a group. +- With `role="group"` and `aria-labelledby` on FormGroup, FormGroup itself is a named group. A unit test confirms that FormGroup passes these attributes to its root element. +- No docs page or demo documents `role="group"` on FormGroup. The docs show only the `fieldset` pattern, in CheckboxesGroup and SwitchesGroup. A follow-up must document the `role="group"` pattern. +- Inside `FormControl component="fieldset"` with `FormLabel component="legend"`, the `fieldset` is the group, and the legend is its name. FormGroup adds nothing to this pattern. +- A group without a `fieldset` or a role has no name. This is the author's responsibility. +- FormControl does not connect a FormHelperText to the group. The author adds `aria-describedby`. In the error state, the checkboxes get no `aria-invalid`, because Checkbox and Switch take only `disabled` from FormControl. +- ARIA does not allow `aria-label` on an element with no role, and assistive technology can ignore it. The FormControlLabelPosition docs demos use this pattern. axe-core `aria-prohibited-attr` reports it only as `incomplete`, and no fixture exercises it. +- In the ScrollPlayground Popper demo, each FormGroup starts with a Typography heading (`h6`), for example "Prevent Overflow". No `fieldset` or `aria-labelledby` connects the heading to the group, so the group has no name. This is a demo issue. + +**Manual testing steps** + +1. Start a screen reader (NVDA with Chrome, or VoiceOver with Safari). In Safari, turn on "Press Tab to highlight each item". +2. In a FormGroup inside `FormControl component="fieldset"` with a legend, press Tab into the group. +3. Listen to the announcement. +4. Do the test again with a FormGroup that has no `fieldset`. + + + +**Pass:** the screen reader announces the group name once when focus enters the group. + +#### 3.3.2 Labels or Instructions · A + +`🚩` · `✅ Supports` · `◐ Shared` + +Tested by: axe-core `form-field-multiple-labels` ✅ + + + +- The legend, or the element that `aria-labelledby` names, is the visible label of the group. FormGroup adds no label of its own. +- The required state of a group is a FormLabel gap. The [FormLabel report](../FormLabel/accessibility.md) rates it under 1.3.1. +- Result from the checkbox, switch, app bar, list, focus-visible, Popper, and CRUD dashboard demos: + - CheckboxesGroup, SwitchesGroup, both FormControlLabelPosition demos, and FocusVisibleCustomIcons have a group label. + - CheckboxLabels, SwitchLabels, CustomizedSwitches, MenuAppBar, InteractiveList, and FullFocusVisibleDemo have no group label. Their controls are separate options, and each control has its own label. In FullFocusVisibleDemo, the "Checkbox" text next to the group is a row caption of the showcase, not a group label. + - EmployeeForm, in the CRUD dashboard template, uses FormGroup as a layout wrapper for the whole form. Each field has its own label. + - ScrollPlayground shows a visible heading above each group. The heading is not connected to the group. See 1.3.1. + +**Manual testing steps** + +1. Check that each checkbox and switch group that asks one question has a visible label. +2. Check that the instructions say how many options the user must select. + + + +**Pass:** each group that asks one question has a visible label and clear instructions. + +### ⚙️ Automated + +#### 1.4.10 Reflow · AA + +`✅ Supports` · `◐ Shared` + +Tested by: Playwright + + + +- The group has `flex-wrap: wrap`, so a row of controls wraps onto more lines. A Playwright test confirms that a row of five checkboxes does not scroll horizontally at 320 CSS px. + + + +#### 2.4.3 Focus Order · A + +`✅ Supports` · `◐ Shared` + +Tested by: unit `FormGroup.test.js` + + + +- The controls are tab stops in DOM order, also with `row`. A test in a real browser confirms that a row group shows its controls from left to right in tab order. + + + +## Not applicable + +- **1.1.1 Non-text Content (A).** FormGroup renders no content of its own. +- **1.2.1 Audio-only and Video-only (Prerecorded) (A), 1.2.2 Captions (Prerecorded) (A), 1.2.3 Audio Description or Media Alternative (Prerecorded) (A), 1.2.4 Captions (Live) (AA), 1.2.5 Audio Description (Prerecorded) (AA).** No audio or video. +- **1.3.4 Orientation (AA).** Sets no orientation lock; a layout concern. +- **1.3.5 Identify Input Purpose (AA).** Collects no information about the user through `autocomplete`. +- **1.4.1 Use of Color (A).** FormGroup renders no color of its own. It gets the `error` class in the error state, but no error style. The legend and the helper text show the error color. +- **1.4.2 Audio Control (A).** Emits no audio. +- **1.4.3 Contrast (Minimum) (AA), 1.4.4 Resize Text (AA), 1.4.5 Images of Text (AA), 1.4.12 Text Spacing (AA).** FormGroup renders no text of its own. The legend and the labels own these criteria. +- **1.4.11 Non-text Contrast (AA).** FormGroup renders no graphical object and no component boundary. +- **1.4.13 Content on Hover or Focus (AA).** Shows no additional content on hover or focus; a `Tooltip` wrapper would own this. +- **2.1.1 Keyboard (A), 2.1.2 No Keyboard Trap (A), 2.4.7 Focus Visible (AA), 2.4.11 Focus Not Obscured (Minimum) (AA), 2.5.2 Pointer Cancellation (A), 2.5.3 Label in Name (A), 2.5.8 Target Size (Minimum) (AA), 3.2.1 On Focus (A), 3.2.2 On Input (A), 3.2.4 Consistent Identification (AA).** FormGroup is not focusable and has no action of its own. The controls inside it cover these. +- **2.1.4 Character Key Shortcuts (A).** Binds no single-character keyboard shortcut. +- **2.2.1 Timing Adjustable (A).** Sets no time limit. +- **2.2.2 Pause, Stop, Hide (A).** No auto-starting moving, blinking, or auto-updating content. +- **2.3.1 Three Flashes or Below Threshold (A).** Nothing flashes. +- **2.4.1 Bypass Blocks (A), 2.4.2 Page Titled (A), 2.4.5 Multiple Ways (AA).** Page or site structure, not a single component. +- **2.4.4 Link Purpose (In Context) (A).** The component renders no links. +- **2.5.1 Pointer Gestures (A), 2.5.4 Motion Actuation (A).** Activates on a simple click; reads no device motion. +- **2.5.7 Dragging Movements (AA).** No drag interactions. +- **3.1.1 Language of Page (A), 3.1.2 Language of Parts (AA).** The component emits no `` and no text of its own. A foreign-language label is the author's phrase to mark. +- **3.2.3 Consistent Navigation (AA).** Covers repeated navigation across a set of pages, not a single component. +- **3.2.6 Consistent Help (A).** Covers consistent placement of help across pages. +- **3.3.1 Error Identification (A), 3.3.3 Error Suggestion (AA), 3.3.4 Error Prevention (Legal, Financial, Data) (AA).** Collects and validates no input; these belong to the form or process. +- **3.3.7 Redundant Entry (A).** Captures no previously entered data to repopulate. +- **3.3.8 Accessible Authentication (Minimum) (AA).** No authentication step; the duty falls on the credential fields. +- **4.1.2 Name, Role, Value (A).** FormGroup sets no role, and its own markup supplies no name. The group role and name pattern is rated under 1.3.1. +- **4.1.3 Status Messages (AA).** Emits no status messages; state changes are covered by 4.1.2. + +## Level AAA + + + +None. FormGroup adds no behavior that a Level AAA criterion tests. + + + +## Scope and test environment + +- **Standard.** WCAG 2.2, Level A and AA. +- **Component version.** `@mui/material` 10.0.0-alpha.0. + + + +- **Scope.** The FormGroup component, with and without a `fieldset`, rendered through its documented API. +- **Automated.** axe-core in the Playwright test harness, on the FormGroup fixture in [`form-group.a11y.json`](../../../../docs/data/material/components/form-group/form-group.a11y.json). Tests are in `FormGroup.test.js`. +- **Assistive-technology review.** Not done yet. The flagged criteria come from a review of the source. A review with NVDA, JAWS, and VoiceOver must still confirm them. + + diff --git a/packages/mui-material/src/accessibility.md b/packages/mui-material/src/accessibility.md index ccd0a626c6386c..a2eb4458fc41d3 100644 --- a/packages/mui-material/src/accessibility.md +++ b/packages/mui-material/src/accessibility.md @@ -189,6 +189,7 @@ Edit the JSON files, not this table. | [Button](./Button/accessibility.md) | 24 | 3 | 0 | 28 | — | 7/27 | | [Checkbox](./Checkbox/accessibility.md) | 24 | 1 | 0 | 30 | — | 3/25 | | [CircularProgress](./CircularProgress/accessibility.md) | 8 | 3 | 0 | 44 | — | 5/11 | +| [FormGroup](./FormGroup/accessibility.md) | 7 | 0 | 0 | 48 | — | 3/7 | | [LinearProgress](./LinearProgress/accessibility.md) | 8 | 3 | 0 | 44 | — | 5/11 | | [Radio](./Radio/accessibility.md) | 24 | 1 | 0 | 30 | — | 2/25 | | [RadioGroup](./RadioGroup/accessibility.md) | 7 | 0 | 0 | 30 | 18 | 3/7 | diff --git a/packages/mui-material/src/manual-testing.md b/packages/mui-material/src/manual-testing.md index 4a34f0df831d0a..b6ef68b70f20e4 100644 --- a/packages/mui-material/src/manual-testing.md +++ b/packages/mui-material/src/manual-testing.md @@ -106,6 +106,15 @@ Run the rows matching what you touched, for the component you touched. - [ ] 🔁 **4.1.2 Name, Role, Value** — name, role, and value are correct for every variant, and the track is silent. - [ ] 🔍 **4.1.3 Status Messages** — the change is announced without the user moving focus to it. It is not by default; add a polite live region in the application to convey it. +## FormGroup + +4 checks · full procedures in [`FormGroup/accessibility.md`](./FormGroup/accessibility.md) + +- [ ] 🔁 **1.3.1 Info and Relationships** — the screen reader announces the group name once when focus enters the group. +- [ ] 🔍 **1.3.2 Meaningful Sequence** — the reading order matches the visual order. +- [ ] 🔍 **2.4.6 Headings and Labels** — each group name tells the purpose of the set, for example "Toppings". +- [ ] 🔁 **3.3.2 Labels or Instructions** — each group that asks one question has a visible label and clear instructions. + ## LinearProgress 8 checks · full procedures in [`LinearProgress/accessibility.md`](./LinearProgress/accessibility.md) diff --git a/test/regressions/a11y/criteriaSuites.mjs b/test/regressions/a11y/criteriaSuites.mjs index c8fcde0fe3808c..472ac3b1495ca0 100644 --- a/test/regressions/a11y/criteriaSuites.mjs +++ b/test/regressions/a11y/criteriaSuites.mjs @@ -28,6 +28,13 @@ export const CSS_LAYOUT_SUITES = [ // The spinner renders no text, so the report rates 1.4.4 and 1.4.12 not applicable. skipCriteria: ['1.4.4', '1.4.12'], }, + { + // FormGroup has no docs page of its own, so the layout suite runs on its a11y fixture. + component: 'FormGroup', + route: '/a11y-form-group/FormGroupA11yStates', + // FormGroup renders no text, so the report rates 1.4.4 and 1.4.12 not applicable. + skipCriteria: ['1.4.4', '1.4.12'], + }, { component: 'LinearProgress', route: '/docs-components-progress/LinearDeterminate', diff --git a/test/regressions/a11y/fixtures/form-group/FormGroupA11yStates.js b/test/regressions/a11y/fixtures/form-group/FormGroupA11yStates.js new file mode 100644 index 00000000000000..d435bd8229ad35 --- /dev/null +++ b/test/regressions/a11y/fixtures/form-group/FormGroupA11yStates.js @@ -0,0 +1,67 @@ +import Stack from '@mui/material/Stack'; +import Checkbox from '@mui/material/Checkbox'; +import FormControl from '@mui/material/FormControl'; +import FormControlLabel from '@mui/material/FormControlLabel'; +import FormGroup from '@mui/material/FormGroup'; +import FormHelperText from '@mui/material/FormHelperText'; +import FormLabel from '@mui/material/FormLabel'; +import Switch from '@mui/material/Switch'; +import Typography from '@mui/material/Typography'; + +// FormGroup renders a div with no role. These groups get their name from a +// fieldset legend or from role="group" with aria-labelledby. The "Remember me" +// group has no name, which is the author's responsibility. The wide row wraps +// in the 320px layout suite. +export default function FormGroupA11yStates() { + return ( + + + Toppings + + } label="Cheese" /> + } label="Mushrooms" /> + + Pick any number. + + + Notifications + + } label="Email" /> + } label="Push" /> + + + + Delivery days + + } label="Monday" /> + } label="Tuesday" /> + + Error: select at least one delivery day. + +
+ Share with + + } label="Team" /> + } label="Company" /> + +
+ + } label="Remember me" /> + + + Interests + + {[ + 'Accessibility', + 'Design systems', + 'Performance', + 'Internationalization', + 'Testing', + ].map((label) => ( + } label={label} /> + ))} + + +
+ ); +} diff --git a/test/regressions/demoMeta.test.ts b/test/regressions/demoMeta.test.ts index 3b66852404ebe8..2bf63a70de01e4 100644 --- a/test/regressions/demoMeta.test.ts +++ b/test/regressions/demoMeta.test.ts @@ -137,6 +137,16 @@ describe('getConfig', () => { ).to.deep.include({ enabled: true, assertions: 'all' }); }); + it('asserts every rule on the FormGroup fixture', () => { + expect( + getConfig(A11Y_RULES, 'test/regressions/a11y/fixtures/form-group/FormGroupA11yStates'), + ).to.deep.equal({ + test: 'test/regressions/a11y/fixtures/form-group/FormGroupA11yStates', + enabled: true, + assertions: 'all', + }); + }); + it('returns undefined for a radio demo outside the enrolment', () => { // The radio-buttons enrolment omits FormControlLabelPlacement. expect( diff --git a/test/regressions/demoMeta.ts b/test/regressions/demoMeta.ts index 6469ebe98df752..053d1a40c1ddbd 100644 --- a/test/regressions/demoMeta.ts +++ b/test/regressions/demoMeta.ts @@ -406,6 +406,13 @@ export const A11Y_RULES: A11yRule[] = [ enabled: true, assertions: 'all', }, + // A11y-only fixture under `test/regressions/a11y/fixtures/form-group/`. + // FormGroup has no docs page, so the fixture owns the `form-group` slug. + { + test: 'test/regressions/a11y/fixtures/form-group/FormGroupA11yStates', + enabled: true, + assertions: 'all', + }, { test: `docs/data/material/components/radio-buttons/{${RADIO_A11Y_DEMOS.join(',')}}`, enabled: true,