-
Notifications
You must be signed in to change notification settings - Fork 54
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
Create rule: a11y-no-title-attribute #453
Merged
Merged
Changes from all commits
Commits
Show all changes
7 commits
Select commit
Hold shift + click to select a range
eb8024c
Create rule: a11y-no-title-attribute
kendallgassner 1cce11e
Merge remote-tracking branch 'origin' into add-a11y-no-title-attribute
kendallgassner b358515
Add tests that check various component mappings
kendallgassner 2941475
Add rule to react config
kendallgassner 92f656d
better docs
kendallgassner 35ef90c
clean
kendallgassner 0d95201
Merge remote-tracking branch 'origin' into add-a11y-no-title-attribute
kendallgassner File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
# Guards against developers using the title attribute (`github/a11y-no-title-attribute`) | ||
|
||
💼 This rule is enabled in the ⚛️ `react` config. | ||
|
||
<!-- end auto-generated rule header --> | ||
|
||
The title attribute is strongly discouraged. The only exception is on an `<iframe>` element. It is hardly useful and cannot be accessed by multiple groups of users including keyboard-only users and mobile users. | ||
|
||
The `title` attribute is commonly set on links, matching the link text. This is redundant and unnecessary so it can be simply be removed. | ||
|
||
If you are considering the `title` attribute to provide supplementary description, consider whether the text in question can be persisted in the design. Alternatively, if it's important to display supplementary text that is hidden by default, consider using an accessible tooltip implementation that uses the aria-labelledby or aria-describedby semantics. Even so, proceed with caution: tooltips should only be used on interactive elements like links or buttons. See [Tooltip alternatives](https://primer.style/design/guides/accessibility/tooltip-alternatives) for more accessible alternatives. | ||
|
||
### Should I use the title attribute to provide an accessible name for an <svg>? | ||
|
||
Use a <title> element instead of the title attribute, or an aria-label. | ||
|
||
## Rule Details | ||
|
||
👎 Examples of **incorrect** code for this rule: | ||
|
||
```jsx | ||
<a src="https://www.github.com" title="A home for all developers"> | ||
GitHub | ||
</a> | ||
``` | ||
|
||
```jsx | ||
<a href="/" title="github.com"> | ||
GitHub | ||
</a> | ||
``` | ||
|
||
```jsx | ||
<span src="https://www.github.com" title="supercalifragilisticexpialidocious"> | ||
supercali... | ||
</span> | ||
``` | ||
|
||
👍 Examples of **correct** code for this rule: | ||
|
||
```jsx | ||
<iframe src="https://www.github.com" title="Github"></iframe> | ||
``` | ||
|
||
## Version |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
const {getProp, getPropValue} = require('jsx-ast-utils') | ||
const {getElementType} = require('../utils/get-element-type') | ||
|
||
const SEMANTIC_ELEMENTS = [ | ||
'a', | ||
'button', | ||
'summary', | ||
'select', | ||
'option', | ||
'textarea', | ||
'input', | ||
'span', | ||
'div', | ||
'p', | ||
'h1', | ||
'h2', | ||
'h3', | ||
'h4', | ||
'h5', | ||
'h6', | ||
'details', | ||
'summary', | ||
'dialog', | ||
'tr', | ||
'th', | ||
'td', | ||
'label', | ||
] | ||
|
||
const ifSemanticElement = (context, node) => { | ||
const elementType = getElementType(context, node.openingElement, true) | ||
|
||
for (const semanticElement of SEMANTIC_ELEMENTS) { | ||
if (elementType === semanticElement) { | ||
return true | ||
} | ||
} | ||
return false | ||
} | ||
|
||
module.exports = { | ||
meta: { | ||
docs: { | ||
description: 'Guards against developers using the title attribute', | ||
url: require('../url')(module), | ||
}, | ||
schema: [], | ||
}, | ||
|
||
create(context) { | ||
return { | ||
JSXElement: node => { | ||
const elementType = getElementType(context, node.openingElement) | ||
if (elementType !== `iframe` && ifSemanticElement(context, node)) { | ||
const titleProp = getPropValue(getProp(node.openingElement.attributes, `title`)) | ||
if (titleProp) { | ||
context.report({ | ||
node, | ||
message: 'The title attribute is not accessible and should never be used unless for an `<iframe>`.', | ||
}) | ||
} | ||
} | ||
}, | ||
} | ||
}, | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -15,12 +15,12 @@ const schema = generateObjSchema({ | |
* because a visually hidden input field might cause a false positive. | ||
* (e.g. fileUpload https://github.com/primer/react/pull/3492) | ||
*/ | ||
const INTERACTIVELEMENTS = ['a', 'button', 'summary', 'select', 'option', 'textarea'] | ||
const INTERACTIVE_ELEMENTS = ['a', 'button', 'summary', 'select', 'option', 'textarea'] | ||
|
||
const checkIfInteractiveElement = (context, node) => { | ||
const elementType = getElementType(context, node.openingElement) | ||
|
||
for (const interactiveElement of INTERACTIVELEMENTS) { | ||
for (const interactiveElement of INTERACTIVE_ELEMENTS) { | ||
if (elementType === interactiveElement) { | ||
return true | ||
} | ||
|
@@ -76,7 +76,6 @@ module.exports = { | |
message: | ||
'Avoid visually hidding interactive elements. Visually hiding interactive elements can be confusing to sighted keyboard users as it appears their focus has been lost when they navigate to the hidden element.', | ||
}) | ||
return | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. just unnessary. |
||
} | ||
}, | ||
} | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
const rule = require('../lib/rules/a11y-no-title-attribute') | ||
const RuleTester = require('eslint').RuleTester | ||
|
||
const ruleTester = new RuleTester({ | ||
parserOptions: { | ||
ecmaVersion: 'latest', | ||
sourceType: 'module', | ||
ecmaFeatures: { | ||
jsx: true, | ||
}, | ||
}, | ||
}) | ||
|
||
const errorMessage = 'The title attribute is not accessible and should never be used unless for an `<iframe>`.' | ||
|
||
ruleTester.run('a11y-no-title-attribute', rule, { | ||
valid: [ | ||
{code: '<button>Submit</button>'}, | ||
{code: '<iframe title="an allowed title">GitHub</iframe>'}, | ||
{code: '<span>some information</span>'}, | ||
{code: '<a href="github.com">GitHub</a>'}, | ||
{ | ||
code: '<Component title="some title">Submit</Component>', | ||
settings: { | ||
github: { | ||
components: { | ||
Component: 'iframe', | ||
}, | ||
}, | ||
}, | ||
}, | ||
{ | ||
// Note: we are only checking semantic elements. We cannot make assumptions about how a React Components is using the title prop. | ||
code: '<Link title="some title">Submit</Link>', | ||
settings: { | ||
github: { | ||
components: { | ||
Link: 'a', | ||
}, | ||
}, | ||
}, | ||
}, | ||
], | ||
invalid: [ | ||
{code: '<a title="some title" href="github.com">GitHub</a>', errors: [{message: errorMessage}]}, | ||
{code: '<span><button title="some title">submit</button></span>', errors: [{message: errorMessage}]}, | ||
{ | ||
code: '<Component as="a" title="some title">Submit</Component>', | ||
errors: [{message: errorMessage}], | ||
settings: { | ||
github: { | ||
components: { | ||
Component: 'iframe', | ||
}, | ||
}, | ||
}, | ||
}, | ||
], | ||
}) |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Most of this is directly from the rails rule. With the exception of the last sentence.