Skip to content

Commit 0ebd800

Browse files
Add Data-grid, table and tree rules to expand enterprise component coverage.
1 parent 2f2d469 commit 0ebd800

12 files changed

+825
-3
lines changed

COVERAGE.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ We currently cover the following components:
2929
- [x] Checkbox
3030
- [] ColorPicker
3131
- [x] Combobox
32-
- [] DataGrid
32+
- [x] DataGrid
3333
- [x] Dialog
3434
- [N/A] Divider
3535
- [] Drawer
@@ -70,7 +70,7 @@ We currently cover the following components:
7070
- [N/A] SwatchPickerRow
7171
- [x] Switch
7272
- [] SearchBox
73-
- [] Table
73+
- [x] Table
7474
- [x] TabList
7575
- [] Tag
7676
- [] InteractionTag
@@ -83,7 +83,7 @@ We currently cover the following components:
8383
- [] Toast
8484
- [x] Toolbar
8585
- [x] Tooltip
86-
- [] Tree
86+
- [x] Tree
8787
- [x] Datepicker
8888
- [N/A] Calendar
8989
- [x] Timepicker
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
# datagrid-needs-labelling
2+
3+
DataGrid components must have accessible labelling for screen readers to understand the data structure and purpose.
4+
5+
## Rule Details
6+
7+
This rule enforces that DataGrid components have proper accessible names and follow ARIA grid patterns for complex data tables. DataGrids present tabular data that requires clear identification for assistive technology users.
8+
9+
DataGrids must have an accessible name provided through one of these methods:
10+
- `aria-label` attribute with descriptive text
11+
- `aria-labelledby` attribute referencing existing label elements
12+
- Wrapping in a `Field` component that provides labeling context
13+
14+
### Noncompliant
15+
16+
```jsx
17+
// Missing any form of accessible labeling
18+
<DataGrid columns={columns} items={employees} />
19+
20+
// Empty or whitespace-only labels
21+
<DataGrid aria-label="" columns={columns} items={data} />
22+
<DataGrid aria-label=" " columns={columns} items={data} />
23+
24+
// Invalid aria-labelledby reference
25+
<DataGrid aria-labelledby="non-existent-id" columns={columns} items={data} />
26+
```
27+
28+
### Compliant
29+
30+
```jsx
31+
// Using aria-label
32+
<DataGrid
33+
aria-label="Employee directory"
34+
columns={columns}
35+
items={employees}
36+
/>
37+
38+
// Using aria-labelledby with existing elements
39+
<Label id="data-grid-title">Sales Report Q3 2024</Label>
40+
<DataGrid
41+
aria-labelledby="data-grid-title"
42+
columns={columns}
43+
items={salesData}
44+
/>
45+
46+
// Wrapped in Field component
47+
<Field label="Product Inventory">
48+
<DataGrid columns={productColumns} items={inventory} />
49+
</Field>
50+
51+
// Best practice: Include row/column counts for large datasets
52+
<DataGrid
53+
aria-label="Financial data with 500 rows and 12 columns"
54+
aria-rowcount={500}
55+
aria-colcount={12}
56+
columns={columns}
57+
items={financialData}
58+
/>
59+
```
60+
61+
## Best Practices
62+
63+
1. **Descriptive Labels**: Use clear, descriptive labels that explain the data's purpose
64+
2. **Data Context**: Include information about the data type (e.g., "Employee directory", "Sales report")
65+
3. **Size Hints**: For large datasets, consider mentioning approximate size in the label
66+
4. **Multiple Labels**: Use `aria-labelledby` to reference multiple elements for richer context
67+
68+
## When Not To Use
69+
70+
This rule should always be used for DataGrid components as they present complex tabular data that requires clear identification for screen reader users.
71+
72+
## Related Rules
73+
74+
- `table-needs-labelling` - Similar requirements for Table components
75+
- `field-needs-labelling` - Field wrapper component labeling
76+
77+
## Accessibility Guidelines
78+
79+
- [WCAG 4.1.2](https://www.w3.org/WAI/WCAG21/Understanding/name-role-value.html)
80+
- [ARIA Grid Pattern](https://www.w3.org/WAI/ARIA/apg/patterns/grid/)
81+
- [ARIA Table Pattern](https://www.w3.org/WAI/ARIA/apg/patterns/table/)
Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
# table-needs-labelling
2+
3+
Table components must have accessible labelling for screen readers to understand the table's purpose and content structure.
4+
5+
## Rule Details
6+
7+
This rule enforces that Table components have proper accessible names following semantic HTML and ARIA best practices. Tables present structured data that requires clear identification for assistive technology users.
8+
9+
Tables must have an accessible name provided through one of these methods:
10+
- `aria-label` attribute with descriptive text
11+
- `aria-labelledby` attribute referencing existing label elements
12+
- `<caption>` element providing semantic table description
13+
- Wrapping in a `Field` component that provides labeling context
14+
15+
### Noncompliant
16+
17+
```jsx
18+
// Missing any form of accessible labeling
19+
<Table>
20+
<TableHeader />
21+
<TableBody />
22+
</Table>
23+
24+
// Empty labels don't provide accessibility
25+
<Table aria-label="">
26+
<TableHeader />
27+
<TableBody />
28+
</Table>
29+
30+
// Invalid reference
31+
<Table aria-labelledby="missing-id">
32+
<TableHeader />
33+
<TableBody />
34+
</Table>
35+
```
36+
37+
### Compliant
38+
39+
```jsx
40+
// Using aria-label
41+
<Table aria-label="Product inventory">
42+
<TableHeader>
43+
<TableRow>
44+
<TableHeaderCell>Product</TableHeaderCell>
45+
<TableHeaderCell>Stock</TableHeaderCell>
46+
</TableRow>
47+
</TableHeader>
48+
<TableBody>
49+
<TableRow>
50+
<TableCell>Widget A</TableCell>
51+
<TableCell>150</TableCell>
52+
</TableRow>
53+
</TableBody>
54+
</Table>
55+
56+
// Using semantic caption element (preferred)
57+
<Table>
58+
<caption>Sales Performance Q3 2024</caption>
59+
<TableHeader />
60+
<TableBody />
61+
</Table>
62+
63+
// Using aria-labelledby
64+
<h2 id="table-title">Employee Directory</h2>
65+
<Table aria-labelledby="table-title">
66+
<TableHeader />
67+
<TableBody />
68+
</Table>
69+
70+
// Wrapped in Field component
71+
<Field label="Financial Summary">
72+
<Table>
73+
<TableHeader />
74+
<TableBody />
75+
</Table>
76+
</Field>
77+
```
78+
79+
## Best Practices
80+
81+
1. **Prefer `<caption>`**: Use caption elements for semantic table labeling when possible
82+
2. **Descriptive Labels**: Clearly describe the table's content and purpose
83+
3. **Context Information**: Include relevant time periods, data scope, or categories
84+
4. **Consistent Structure**: Ensure tables have proper TableHeader and TableBody elements
85+
86+
## When Not To Use
87+
88+
This rule should always be used for Table components as they present structured data that requires clear identification for screen reader users.
89+
90+
## Related Rules
91+
92+
- `datagrid-needs-labelling` - Similar requirements for DataGrid components
93+
- `field-needs-labelling` - Field wrapper component labeling
94+
95+
## Accessibility Guidelines
96+
97+
- [WCAG 4.1.2](https://www.w3.org/WAI/WCAG21/Understanding/name-role-value.html)
98+
- [ARIA Table Pattern](https://www.w3.org/WAI/ARIA/apg/patterns/table/)
99+
- [HTML Table Accessibility](https://webaim.org/techniques/tables/)

docs/rules/tree-needs-labelling.md

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
# tree-needs-labelling
2+
3+
Tree components must have accessible labelling for screen readers to understand the hierarchical structure and navigation purpose.
4+
5+
## Rule Details
6+
7+
This rule enforces that Tree components have proper accessible names following ARIA tree pattern guidelines. Trees present hierarchical data that requires clear identification for assistive technology users to understand the navigation context.
8+
9+
Trees must have an accessible name provided through one of these methods:
10+
- `aria-label` attribute with descriptive text
11+
- `aria-labelledby` attribute referencing existing label elements
12+
- Wrapping in a `Field` component that provides labeling context
13+
14+
### Noncompliant
15+
16+
```jsx
17+
// Missing any form of accessible labeling
18+
<Tree>
19+
<TreeItem>Folder 1</TreeItem>
20+
<TreeItem>Folder 2</TreeItem>
21+
</Tree>
22+
23+
// Empty or whitespace-only labels
24+
<Tree aria-label="">
25+
<TreeItem>Item 1</TreeItem>
26+
</Tree>
27+
28+
// Invalid aria-labelledby reference
29+
<Tree aria-labelledby="non-existent-id">
30+
<TreeItem>Item 1</TreeItem>
31+
</Tree>
32+
```
33+
34+
### Compliant
35+
36+
```jsx
37+
// Using aria-label
38+
<Tree aria-label="File explorer">
39+
<TreeItem>
40+
<TreeItemLayout>Documents</TreeItemLayout>
41+
<Tree>
42+
<TreeItem>Resume.pdf</TreeItem>
43+
<TreeItem>Cover Letter.docx</TreeItem>
44+
</Tree>
45+
</TreeItem>
46+
<TreeItem>Images</TreeItem>
47+
</Tree>
48+
49+
// Using aria-labelledby
50+
<h3 id="nav-tree">Site Navigation</h3>
51+
<Tree aria-labelledby="nav-tree">
52+
<TreeItem>Home</TreeItem>
53+
<TreeItem>Products</TreeItem>
54+
<TreeItem>Contact</TreeItem>
55+
</Tree>
56+
57+
// Wrapped in Field component
58+
<Field label="Organization Chart">
59+
<Tree>
60+
<TreeItem>CEO</TreeItem>
61+
<TreeItem>VP Engineering</TreeItem>
62+
</Tree>
63+
</Field>
64+
65+
// Complex labeling with instructions
66+
<h3 id="tree-title">Project Files</h3>
67+
<p id="tree-instructions">Use arrow keys to navigate, Enter to open</p>
68+
<Tree aria-labelledby="tree-title tree-instructions">
69+
<TreeItem>src/</TreeItem>
70+
<TreeItem>docs/</TreeItem>
71+
<TreeItem>tests/</TreeItem>
72+
</Tree>
73+
```
74+
75+
## Best Practices
76+
77+
1. **Context Description**: Clearly describe what the tree represents (file system, navigation, org chart)
78+
2. **Navigation Hints**: Consider including keyboard navigation instructions in labels
79+
3. **Scope Information**: Indicate the breadth or type of items in the tree
80+
4. **Hierarchical Context**: Help users understand the tree's organizational purpose
81+
82+
## When Not To Use
83+
84+
This rule should always be used for Tree components as they present complex hierarchical navigation that requires clear identification for screen reader users.
85+
86+
## Related Rules
87+
88+
- `field-needs-labelling` - Field wrapper component labeling
89+
90+
## Accessibility Guidelines
91+
92+
- [WCAG 4.1.2](https://www.w3.org/WAI/WCAG21/Understanding/name-role-value.html)
93+
- [ARIA Tree Pattern](https://www.w3.org/WAI/ARIA/apg/patterns/treeview/)
94+
- [ARIA Navigation Landmarks](https://www.w3.org/WAI/ARIA/apg/practices/landmark-regions/)

lib/index.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ module.exports = {
2727
"@microsoft/fluentui-jsx-a11y/combobox-needs-labelling": "error",
2828
"@microsoft/fluentui-jsx-a11y/compound-button-needs-labelling": "error",
2929
"@microsoft/fluentui-jsx-a11y/counter-badge-needs-count": "error",
30+
"@microsoft/fluentui-jsx-a11y/datagrid-needs-labelling": "error",
3031
"@microsoft/fluentui-jsx-a11y/dialogbody-needs-title-content-and-actions": "error",
3132
"@microsoft/fluentui-jsx-a11y/dialogsurface-needs-aria": "error",
3233
"@microsoft/fluentui-jsx-a11y/dropdown-needs-labelling": "error",
@@ -50,11 +51,13 @@ module.exports = {
5051
"@microsoft/fluentui-jsx-a11y/spin-button-unrecommended-labelling": "error",
5152
"@microsoft/fluentui-jsx-a11y/spinner-needs-labelling": "error",
5253
"@microsoft/fluentui-jsx-a11y/switch-needs-labelling": "error",
54+
"@microsoft/fluentui-jsx-a11y/table-needs-labelling": "error",
5355
"@microsoft/fluentui-jsx-a11y/tablist-and-tabs-need-labelling": "error",
5456
"@microsoft/fluentui-jsx-a11y/tag-dismissible-needs-labelling": "error",
5557
"@microsoft/fluentui-jsx-a11y/tag-needs-name": "error",
5658
"@microsoft/fluentui-jsx-a11y/toolbar-missing-aria": "error",
5759
"@microsoft/fluentui-jsx-a11y/tooltip-not-recommended": "error",
60+
"@microsoft/fluentui-jsx-a11y/tree-needs-labelling": "error",
5861
"@microsoft/fluentui-jsx-a11y/visual-label-better-than-aria-suggestion": "warn"
5962
}
6063
}
@@ -71,6 +74,7 @@ module.exports = {
7174
"combobox-needs-labelling": rules.comboboxNeedsLabelling,
7275
"compound-button-needs-labelling": rules.compoundButtonNeedsLabelling,
7376
"counter-badge-needs-count": rules.counterBadgeNeedsCount,
77+
"datagrid-needs-labelling": rules.dataGridNeedsLabelling,
7478
"dialogbody-needs-title-content-and-actions": rules.dialogbodyNeedsTitleContentAndActions,
7579
"dialogsurface-needs-aria": rules.dialogsurfaceNeedsAria,
7680
"dropdown-needs-labelling": rules.dropdownNeedsLabelling,
@@ -94,11 +98,13 @@ module.exports = {
9498
"spin-button-unrecommended-labelling": rules.spinButtonUnrecommendedLabelling,
9599
"spinner-needs-labelling": rules.spinnerNeedsLabelling,
96100
"switch-needs-labelling": rules.switchNeedsLabelling,
101+
"table-needs-labelling": rules.tableNeedsLabelling,
97102
"tablist-and-tabs-need-labelling": rules.tablistAndTabsNeedLabelling,
98103
"tag-dismissible-needs-labelling": rules.tagDismissibleNeedsLabelling,
99104
"tag-needs-name": rules.tagNeedsName,
100105
"toolbar-missing-aria": rules.toolbarMissingAria,
101106
"tooltip-not-recommended": rules.tooltipNotRecommended,
107+
"tree-needs-labelling": rules.treeNeedsLabelling,
102108
"visual-label-better-than-aria-suggestion": rules.visualLabelBetterThanAriaSuggestion
103109
}
104110
};

0 commit comments

Comments
 (0)