Skip to content
Open
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion COVERAGE.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ We currently cover the following components:
- [X] CompoundButton
- [] MenuButton
- [X] MenuItem
- [] SplitButton
- [x] SplitButton
- [x] ToggleButton
- [] ToolbarToggleButton
- [] Card
Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,7 @@ Any use of third-party trademarks or logos are subject to those third-party's po
| [spin-button-needs-labelling](docs/rules/spin-button-needs-labelling.md) | Accessibility: SpinButtons must have an accessible label | ✅ | | |
| [spin-button-unrecommended-labelling](docs/rules/spin-button-unrecommended-labelling.md) | Accessibility: Unrecommended accessibility labelling - SpinButton | ✅ | | |
| [spinner-needs-labelling](docs/rules/spinner-needs-labelling.md) | Accessibility: Spinner must have either aria-label or label, aria-live and aria-busy attributes | ✅ | | |
| [split-button-needs-labelling](docs/rules/split-button-needs-labelling.md) | Accessibility: SplitButton must have an accessible name via title, aria-label | ✅ | | |
| [swatchpicker-needs-labelling](docs/rules/swatchpicker-needs-labelling.md) | Accessibility: SwatchPicker must have an accessible name via aria-label, aria-labelledby, Field component, etc.. | ✅ | | |
| [switch-needs-labelling](docs/rules/switch-needs-labelling.md) | Accessibility: Switch must have an accessible label | ✅ | | |
| [tablist-and-tabs-need-labelling](docs/rules/tablist-and-tabs-need-labelling.md) | This rule aims to ensure that Tabs with icons but no text labels have an accessible name and that Tablist is properly labeled. | ✅ | | |
Expand Down
38 changes: 38 additions & 0 deletions docs/rules/split-button-needs-labelling.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# Accessibility: SplitButton must have an accessible name via title, aria-label (`@microsoft/fluentui-jsx-a11y/split-button-needs-labelling`)

💼 This rule is enabled in the ✅ `recommended` config.

<!-- end auto-generated rule header -->

SplitButton without a label or accessible labeling lack an accessible name for assistive technology users.

SplitButton components need a visual label.

Please add label, or aria-labelledby.

<https://www.w3.org/WAI/standards-guidelines/act/rules/97a4e1/>

## Rule Details

This rule aims to...

Examples of **incorrect** code for this rule:

```jsx
<SplitButton> Example</SplitButton>
```

```jsx
<SplitButton disabled> Example</SplitButton>
```


Examples of **correct** code for this rule:

```jsx
<SplitButton aria-label="My button">Example</SplitButton>
```

```jsx
<SplitButton disabled aria-label="My button">Disabled State</SplitButton>
```
2 changes: 2 additions & 0 deletions lib/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ module.exports = {
"@microsoft/fluentui-jsx-a11y/spin-button-needs-labelling": "error",
"@microsoft/fluentui-jsx-a11y/spin-button-unrecommended-labelling": "error",
"@microsoft/fluentui-jsx-a11y/spinner-needs-labelling": "error",
"@microsoft/fluentui-jsx-a11y/split-button-needs-labelling": "error",
"@microsoft/fluentui-jsx-a11y/swatchpicker-needs-labelling": "error",
"@microsoft/fluentui-jsx-a11y/switch-needs-labelling": "error",
"@microsoft/fluentui-jsx-a11y/tablist-and-tabs-need-labelling": "error",
Expand Down Expand Up @@ -88,6 +89,7 @@ module.exports = {
"spin-button-needs-labelling": rules.spinButtonNeedsLabelling,
"spin-button-unrecommended-labelling": rules.spinButtonUnrecommendedLabelling,
"spinner-needs-labelling": rules.spinnerNeedsLabelling,
"split-button-needs-labelling": rules.splitButtonNeedsLabelling,
"swatchpicker-needs-labelling": rules.swatchpickerNeedsLabelling,
"switch-needs-labelling": rules.switchNeedsLabelling,
"tablist-and-tabs-need-labelling": rules.tablistAndTabsNeedLabelling,
Expand Down
1 change: 1 addition & 0 deletions lib/rules/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ export { default as imageSwatchNeedsLabelling } from "./imageswatch-needs-labell
export { default as spinButtonNeedsLabelling } from "./spin-button-needs-labelling";
export { default as spinButtonUnrecommendedLabelling } from "./spin-button-unrecommended-labelling";
export { default as spinnerNeedsLabelling } from "./spinner-needs-labelling";
export { default as splitButtonNeedsLabelling } from "./split-button-needs-labelling";
export { default as swatchpickerNeedsLabelling } from "./swatchpicker-needs-labelling";
export { default as switchNeedsLabelling } from "./switch-needs-labelling";
export { default as tablistAndTabsNeedLabelling } from "./tablist-and-tabs-need-labelling";
Expand Down
25 changes: 25 additions & 0 deletions lib/rules/split-button-needs-labelling.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.

import { ESLintUtils } from "@typescript-eslint/utils";
import { makeLabeledControlRule } from "../util/ruleFactory";

//------------------------------------------------------------------------------
// Rule Definition
//------------------------------------------------------------------------------

export default ESLintUtils.RuleCreator.withoutDocs(
makeLabeledControlRule({
component: "SplitButton",
messageId: "noUnlabeledSplitButton",
description: "Accessibility: SplitButton must have an accessible name via title, aria-label",
labelProps: ["aria-label"],
allowFieldParent: true,
allowHtmlFor: false,
allowLabelledBy: true,
allowWrappingLabel: false,
allowTooltipParent: false,
allowDescribedBy: false,
allowLabeledChild: false
})
);
65 changes: 65 additions & 0 deletions tests/lib/rules/split-button-needs-labelling-test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.

import { Rule } from "eslint";
import ruleTester from "./helper/ruleTester";
import rule from "../../../lib/rules/split-button-needs-labelling";
// -----------------------------------------------------------------------------
// Tests
// -----------------------------------------------------------------------------

ruleTester.run("split-button-needs-labelling", rule as unknown as Rule.RuleModule, {
valid: [
// 1) aria-label on the SplitButton

`<SplitButton aria-label="Example">Example</SplitButton>
`,
// 2) disabled SplitButton with aria-label
`
<SplitButton aria-label="Example" disabled> Disabled State </SplitButton>
`,
`<>
<span id="splitButton">Choose Values</span>
<SplitButton aria-labelledby="splitButton"> Example
</SplitButton>
</>`
],

invalid: [
// Unlabeled SplitButton
{
code: `
<SplitButton>Example</SplitButton>
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is actually valid

`,
errors: [{ messageId: "noUnlabeledSplitButton" }]
},
// disabled SplitButton without aria-label
{
code: `
<SplitButton disabled>Example</SplitButton>
`,
errors: [{ messageId: "noUnlabeledSplitButton" }]
},
// SplitButton with empty aria-label
{
code: `
<SplitButton aria-label="">Example</SplitButton>
`,
errors: [{ messageId: "noUnlabeledSplitButton" }]
},
// SplitButton with aria-label undefined
{
code: `
<SplitButton aria-label={undefined}>Example</SplitButton>
`,
errors: [{ messageId: "noUnlabeledSplitButton" }]
},
// SplitButton with aria-label null
{
code: `
<SplitButton aria-label={null}>Example</SplitButton>
`,
errors: [{ messageId: "noUnlabeledSplitButton" }]
}
]
});
Loading