Skip to content

User/aubreyquinn/ts converstion #132

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 10 commits into from
Nov 8, 2024
Merged
Show file tree
Hide file tree
Changes from all 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
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ Any use of third-party trademarks or logos are subject to those third-party's po
| [dialogbody-needs-title-content-and-actions](docs/rules/dialogbody-needs-title-content-and-actions.md) | A DialogBody should have a header(DialogTitle), content(DialogContent), and footer(DialogActions) | ✅ | | |
| [dialogsurface-needs-aria](docs/rules/dialogsurface-needs-aria.md) | DialogueSurface need accessible labelling: aria-describedby on DialogueSurface and aria-label or aria-labelledby(if DialogueTitle is missing) | ✅ | | |
| [dropdown-needs-labelling](docs/rules/dropdown-needs-labelling.md) | Accessibility: Dropdown menu must have an id and it needs to be linked via htmlFor of a Label | ✅ | | |
| [field-needs-labelling](docs/rules/field-needs-labelling.md) | Accessibility: Field must have either label, validationMessage and hint attributes | ✅ | | |
| [field-needs-labelling](docs/rules/field-needs-labelling.md) | Accessibility: Field must have label | ✅ | | |
| [image-button-missing-aria](docs/rules/image-button-missing-aria.md) | Accessibility: Image buttons must have accessible labelling: title, aria-label, aria-labelledby, aria-describedby | ✅ | | |
| [input-components-require-accessible-name](docs/rules/input-components-require-accessible-name.md) | Accessibility: Input fields must have accessible labelling: aria-label, aria-labelledby or an associated label | ✅ | | |
| [link-missing-labelling](docs/rules/link-missing-labelling.md) | Accessibility: Image links must have an accessible name. Add either text content, labelling to the image or labelling to the link itself. | ✅ | | 🔧 |
Expand All @@ -141,6 +141,6 @@ Any use of third-party trademarks or logos are subject to those third-party's po
| [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. | ✅ | | |
| [toolbar-missing-aria](docs/rules/toolbar-missing-aria.md) | Accessibility: Toolbars need accessible labelling: aria-label or aria-labelledby | ✅ | | |
| [tooltip-not-recommended](docs/rules/tooltip-not-recommended.md) | Accessibility: Prefer text content or aria over a tooltip for these components MenuItem, SpinButton | ✅ | | |
| [visual-label-better-than-aria-suggestion](docs/rules/visual-label-better-than-aria-suggestion.md) | Visual label is better than an aria-label | | ✅ | |
| [visual-label-better-than-aria-suggestion](docs/rules/visual-label-better-than-aria-suggestion.md) | Visual label is better than an aria-label because sighted users can't read the aria-label text. | | ✅ | |

<!-- end auto-generated rules list -->
33 changes: 12 additions & 21 deletions docs/rules/field-needs-labelling.md
Original file line number Diff line number Diff line change
@@ -1,18 +1,17 @@
# Accessibility: Field must have either label, validationMessage and hint attributes (`@microsoft/fluentui-jsx-a11y/field-needs-labelling`)
# Accessibility: Field must have label (`@microsoft/fluentui-jsx-a11y/field-needs-labelling`)

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

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

Field must have `label` prop and either `validationMessage` or `hint` prop.
Field must have `label` prop.

<https://www.w3.org/TR/html-aria/>

## Ways to fix

- Make sure that Field component has following props:
- `label`
- `validationMessage` or `hint`

## Rule Details

Expand All @@ -21,41 +20,33 @@ This rule aims to make Field component accessible.
Examples of **incorrect** code for this rule:

```jsx
<Field
label="Example field"
validationState="success"
>
<Field label="Example field" validationState="success">
<ProgressBar value={0.5} max={1} />
</Field>
```

```jsx
<Field
validationState="success"
hint="This is a hint."
>
<Field validationState="success" hint="This is a hint.">
<ProgressBar value={0.5} max={1} />
</Field>
```

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

```jsx
<Field
label="Example field"
validationState="success"
validationMessage="This is a success message."
>
<Field label="Example field">
<Input />
</Field>
```

```jsx
<Field label="Example field" validationState="success" validationMessage="This is a success message.">
<ProgressBar value={0.5} max={1} />
</Field>
```

```jsx
<Field
label="Example field"
validationState="success"
hint="This is a hint."
>
<Field label="Example field" validationState="success" hint="This is a hint.">
<ProgressBar value={0.5} max={1} />
</Field>
```
2 changes: 1 addition & 1 deletion docs/rules/visual-label-better-than-aria-suggestion.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Visual label is better than an aria-label (`@microsoft/fluentui-jsx-a11y/visual-label-better-than-aria-suggestion`)
# Visual label is better than an aria-label because sighted users can't read the aria-label text (`@microsoft/fluentui-jsx-a11y/visual-label-better-than-aria-suggestion`)

⚠️ This rule _warns_ in the ✅ `recommended` config.

Expand Down
4 changes: 4 additions & 0 deletions lib/applicableComponents/labelBasedComponents.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
const labelBasedComponents = ["Label", "label"];
const elementsUsedAsLabels = ["div", "span", "p", "h1", "h2", "h3", "h4", "h5", "h6"];

export { labelBasedComponents, elementsUsedAsLabels };
Original file line number Diff line number Diff line change
Expand Up @@ -5,41 +5,41 @@

const { hasNonEmptyProp } = require("../util/hasNonEmptyProp");
const elementType = require("jsx-ast-utils").elementType;
import { ESLintUtils, TSESTree } from "@typescript-eslint/utils";

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

module.exports = {
const rule = ESLintUtils.RuleCreator.withoutDocs({
defaultOptions: [],
meta: {
// possible error messages for the rule
messages: {
noUnlabelledField: "Accessibility: Field must have either label, validationMessage and hint attributes"
noUnlabelledField: "Accessibility: Field must have label"
},
// "problem" means the rule is identifying code that either will cause an error or may cause a confusing behavior: https://eslint.org/docs/latest/developer-guide/working-with-rules
type: "problem",
// docs for the rule
docs: {
description: "Accessibility: Field must have either label, validationMessage and hint attributes",
recommended: true,
description: "Accessibility: Field must have label",
recommended: "strict",
url: "https://www.w3.org/TR/html-aria/" // URL to the documentation page for this rule
},
schema: []
},

// create (function) returns an object with methods that ESLint calls to “visit” nodes while traversing the abstract syntax tree
create(context) {
return {
// visitor functions for different types of nodes
JSXOpeningElement(node) {
JSXOpeningElement(node: TSESTree.JSXOpeningElement) {
// if it is not a Spinner, return
if (elementType(node) !== "Field") {
return;
}

if (
hasNonEmptyProp(node.attributes, "label", true) &&
(hasNonEmptyProp(node.attributes, "validationMessage", true) || hasNonEmptyProp(node.attributes, "hint", true))
) {
if (hasNonEmptyProp(node.attributes, "label")) {
return;
}

Expand All @@ -51,5 +51,6 @@ module.exports = {
}
};
}
};
});

export default rule;
4 changes: 3 additions & 1 deletion lib/rules/input-components-require-accessible-name.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { isInsideLabelTag, hasAssociatedLabelViaHtmlFor, hasAssociatedLabelViaAr
import { hasFieldParent } from "../util/hasFieldParent";
import { applicableComponents } from "../applicableComponents/inputBasedComponents";
import { JSXOpeningElement } from "estree-jsx";
import { hasNonEmptyProp } from "../util/hasNonEmptyProp";

//------------------------------------------------------------------------------
// Rule Definition
Expand All @@ -17,7 +18,7 @@ const rule = ESLintUtils.RuleCreator.withoutDocs({
meta: {
// possible error messages for the rule
messages: {
missingLabelOnInput: `Accessibility - input fields must have a aria label associated with it: ${applicableComponents.join(
missingLabelOnInput: `Accessibility - input fields must have an accessible label associated with it: ${applicableComponents.join(
", "
)}`
},
Expand All @@ -43,6 +44,7 @@ const rule = ESLintUtils.RuleCreator.withoutDocs({

// wrapped in Label tag, labelled with htmlFor, labelled with aria-labelledby
if (
hasNonEmptyProp(node.attributes, "aria-label") ||
hasFieldParent(context) ||
isInsideLabelTag(context) ||
hasAssociatedLabelViaHtmlFor(node, context) ||
Expand Down
76 changes: 0 additions & 76 deletions lib/rules/tablist-and-tabs-need-labelling.js

This file was deleted.

77 changes: 77 additions & 0 deletions lib/rules/tablist-and-tabs-need-labelling.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.

import { ESLintUtils, TSESTree } from "@typescript-eslint/utils";
import { hasTextContentChild } from "../util/hasTextContentChild";
import { hasNonEmptyProp } from "../util/hasNonEmptyProp";
import { hasAssociatedLabelViaAriaLabelledBy } from "../util/labelUtils";
import { elementType } from "jsx-ast-utils";
import { JSXOpeningElement } from "estree-jsx";

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

const rule = ESLintUtils.RuleCreator.withoutDocs({
defaultOptions: [],
meta: {
type: "problem",
docs: {
description:
"This rule aims to ensure that Tabs with icons but no text labels have an accessible name and that Tablist is properly labeled.",
recommended: "strict",
url: "https://www.w3.org/WAI/ARIA/apg/patterns/tabs/" // URL to the documentation page for this rule
},
fixable: undefined,
schema: [],
messages: {
missingTabLabel: "Accessibility: Tab elements must have an aria-label attribute is there is no visiable text content",
missingTablistLabel: "Accessibility: Tablist must have an accessible label"
}
},

create(context) {
return {
// visitor functions for different types of nodes
JSXOpeningElement(node: TSESTree.JSXOpeningElement) {
const elementTypeValue = elementType(node as unknown as JSXOpeningElement);

// if it is not a Tablist or Tab, return
if (elementTypeValue !== "Tablist" && elementTypeValue !== "Tab") {
return;
}

// Check for Tablist elements
if (elementTypeValue === "Tablist") {
if (
// if the Tablist has a label, if the Tablist has an associated label, return
hasNonEmptyProp(node.attributes, "aria-label") || //aria-label
hasAssociatedLabelViaAriaLabelledBy(node, context) // aria-labelledby
) {
return;
}
context.report({
node,
messageId: "missingTablistLabel"
});
}

// Check for Tab elements
if (elementTypeValue === "Tab") {
if (
hasTextContentChild(node.parent as unknown as TSESTree.JSXElement) || // text content
hasNonEmptyProp(node.attributes, "aria-label") // aria-label
) {
return;
}
context.report({
node,
messageId: "missingTabLabel"
});
}
}
};
}
});

export default rule;
Loading
Loading