From 3669d45815e8484d29083aeecf5bbabc23e4a2ec Mon Sep 17 00:00:00 2001 From: Aditi Ojha Date: Wed, 17 Sep 2025 13:22:17 +0200 Subject: [PATCH 1/9] SplitButton needs label --- COVERAGE.md | 2 +- docs/rules/splitButton-needs-labelling.md | 41 +++++++++++++++++++ .../buttons/splitButton-needs-labelling.ts | 25 +++++++++++ lib/rules/index.ts | 1 + .../splitButton-needs-labelling.test.ts | 39 ++++++++++++++++++ 5 files changed, 107 insertions(+), 1 deletion(-) create mode 100644 docs/rules/splitButton-needs-labelling.md create mode 100644 lib/rules/buttons/splitButton-needs-labelling.ts create mode 100644 tests/lib/rules/buttons/splitButton-needs-labelling.test.ts diff --git a/COVERAGE.md b/COVERAGE.md index d65a83b..89b7f91 100644 --- a/COVERAGE.md +++ b/COVERAGE.md @@ -15,7 +15,7 @@ We currently cover the following components: - [X] CompoundButton - [] MenuButton - [X] MenuItem - - [] SplitButton + - [x] SplitButton - [x] ToggleButton - [] ToolbarToggleButton - [] Card diff --git a/docs/rules/splitButton-needs-labelling.md b/docs/rules/splitButton-needs-labelling.md new file mode 100644 index 0000000..c345421 --- /dev/null +++ b/docs/rules/splitButton-needs-labelling.md @@ -0,0 +1,41 @@ +# Accessibility: SplitButton must have an accessible label (`@microsoft/fluentui-jsx-a11y/splitButton-needs-labelling`) + +💼 This rule is enabled in the ✅ `recommended` config. + + + +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. + + + +## Rule Details + +This rule aims to... + +Examples of **incorrect** code for this rule: + +```jsx + +``` + +```jsx + +``` + +Examples of **correct** code for this rule: + +```jsx + Example +``` + +```jsx + +``` + +```jsx +Disabled State +``` \ No newline at end of file diff --git a/lib/rules/buttons/splitButton-needs-labelling.ts b/lib/rules/buttons/splitButton-needs-labelling.ts new file mode 100644 index 0000000..10bcda0 --- /dev/null +++ b/lib/rules/buttons/splitButton-needs-labelling.ts @@ -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 + }) +); diff --git a/lib/rules/index.ts b/lib/rules/index.ts index bfdbe7b..114fa86 100644 --- a/lib/rules/index.ts +++ b/lib/rules/index.ts @@ -20,6 +20,7 @@ export { default as inputComponentsRequireAccessibleName } from "./input-compone export { default as linkMissingLabelling } from "./link-missing-labelling"; export { default as menuItemNeedsLabelling } from "./menu-item-needs-labelling"; export { default as noEmptyButtons } from "./buttons/no-empty-buttons"; +export { default as splitButtonNeedsLabelling } from "./buttons/splitButton-needs-labelling"; export { default as noEmptyComponents } from "./no-empty-components"; export { default as preferAriaOverTitleAttribute } from "./prefer-aria-over-title-attribute"; export { default as progressbarNeedsLabelling } from "./progressbar-needs-labelling"; diff --git a/tests/lib/rules/buttons/splitButton-needs-labelling.test.ts b/tests/lib/rules/buttons/splitButton-needs-labelling.test.ts new file mode 100644 index 0000000..482076e --- /dev/null +++ b/tests/lib/rules/buttons/splitButton-needs-labelling.test.ts @@ -0,0 +1,39 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +import { Rule } from "eslint"; +import ruleTester from "../helper/ruleTester"; +import rule from "../../../../lib/rules/buttons/splitButton-needs-labelling"; +// ----------------------------------------------------------------------------- +// Tests +// ----------------------------------------------------------------------------- + +ruleTester.run("splitButton-needs-labelling", rule as unknown as Rule.RuleModule, { + valid: [ + // 1) aria-label on the SplitButton + + `Example + `, + // 2) Field wrapper with label prop + ` + Disabled State + ` + ], + + invalid: [ + // Unlabeled SwatchPicker (children present, but no accessible name) + { + code: ` + Example + `, + errors: [{ messageId: "noUnlabeledSplitButton" }] + }, + { + // 7) Native