Skip to content
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

Add accessibility rule and React config #282

Merged
merged 13 commits into from Jul 21, 2022
Merged

Add accessibility rule and React config #282

merged 13 commits into from Jul 21, 2022

Conversation

khiga8
Copy link
Contributor

@khiga8 khiga8 commented Jul 19, 2022

Relates to: github/accessibility#1403 (GitHub staff only)

CC: @github/accessibility-reviewers too for any thoughts

Motivation

We want to start creating and sharing custom accessibility rules for React projects. While there is a jsx-plugin-a11y, GitHub also has some opinionated stances when it comes to accessibility which we want to codify with a linter.

I noticed that GitHub already owns a couple open-source eslint repos so I decided to start adding accessibility rules in this repo rather than starting from scratch. I am thinking that non Primer-specific accessibility rules belong in this repo, while Primer-specific accessibility rules can go in eslint-plugin-primer-react. GitHub staff should check out the following links for more context:

Changes

I am trying to set up a foundation for more accessibility rules to be added and shared between GitHub React projects.

New accessibility rule

I am adding an accessibility rule that discourages use of generic link text in JSX elements. This is the equivalent of an existing ERB lint rule we have (avoid-generic-link-text-counter.md). We want to flag when a link element has an aria-label with generic link text, or when there is no aria-label set but it has a text content of a generic link text.

This is the first time I am writing an eslint rule so please review carefully.

New config

Should I name this to something specific to JSX accessibility linting like jsx-a11y so the config is: github/jsx-a11y?
Or is generic react fine?

Note to reviewer 📣

I'm pretty new to eslint and eslint best practices so if any of this organization seems really funky, please let me know.

Also if you think accessibility rulesets should be organized in a different way or should be in its own repo talk to me! I am in spike phase right now and very open to suggestions/iteration.

lib/index.js Outdated
@@ -9,6 +9,7 @@ module.exports = {
'no-blur': require('./rules/no-blur'),
'no-d-none': require('./rules/no-d-none'),
'no-dataset': require('./rules/no-dataset'),
'no-generic-link-text': require('./rules/no-generic-link-text'),
Copy link
Contributor Author

@khiga8 khiga8 Jul 19, 2022

Choose a reason for hiding this comment

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

I want this to be prefixed so I can pattern match the code base specifically for accessibility rules. What should I do??? Thoughts on just prefixing all accessibility rules like:

a11y-no-generic-link-text

Related Slack thread on prefixing eslint rules (GitHub Staff only)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I changed the name to a11y-

Copy link
Contributor

Choose a reason for hiding this comment

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

I like the a11y!

browser: true
},
plugins: ['github', 'jsx-a11y'],
extends: ['plugin:jsx-a11y/recommended'],
Copy link
Contributor Author

Choose a reason for hiding this comment

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

I'm assuming that any config we want to recommend as part of "react" belongs here, so I added the jsx-a11y plugin. does this look right?

@accessibility-bot
Copy link

👋 Hello and thanks for pinging us! An accessibility first responder will review this soon.

  • 💻 On PRs for our review: please provide a review environment with steps to validate, screenshots (with alt text), or videos demonstrating functionality we should be checking. This will help speed up our review and feedback cycle.
  • ⚠️ If this is urgent, please visit us in #accessibility on Slack and tag the first responder(s) listed in the channel topic.

@@ -0,0 +1,83 @@
# No Generic Link Text
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This is pretty much copied from our erblint-github docs though the examples were changed to .jsx instead of .erb.

The two behave nearly exactly the same so why not 🤷🏻‍♀️

"eslint-plugin-no-only-tests": "^2.6.0",
"eslint-plugin-prettier": "^4.0.0",
"eslint-rule-documentation": ">=1.0.0",
"jsx-ast-utils": "^3.3.2",
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This provides utility methods that make parsing JSX elements much more pleasant. I found it through jsx-a11y-plugin.

Repo for jsx-ast-utils

Copy link
Contributor

Choose a reason for hiding this comment

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

do u also need to use the typescript ast?

Copy link
Contributor

Choose a reason for hiding this comment

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

I guess I am asking does this rule work for tsx files?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It seems yes, as long as the .eslintrc.json wherever the linters get run is configured with the typescript parser:

 "parser": "@typescript-eslint/parser",

I tested this branch out in dotcom by running:

npm i git://github.com/github/eslint-plugin-github.git#kh-add-a11y --save

(^today I learned how to install a package from a GitHub branch!!!)

I see the lint error show up as expected in my editor!

Screenshot of my VSCode editor in dotcom which flags an eslint violation from this rule

Copy link
Contributor

Choose a reason for hiding this comment

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

🕺 ! YAY thanks for checking

@khiga8 khiga8 marked this pull request as ready for review July 19, 2022 01:03
@khiga8 khiga8 requested a review from a team as a code owner July 19, 2022 01:03
@khiga8 khiga8 requested a review from jfuchs July 19, 2022 01:03
@@ -0,0 +1,10 @@
module.exports = {
Copy link
Contributor Author

@khiga8 khiga8 Jul 19, 2022

Choose a reason for hiding this comment

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

Maybe I should distinguish this config as being accessibility rules for react....like github/jsx-a11y. (We don't currently have any other React rules so it's currently just github/react .)

thoughts? @github/accessibility-reviewers . also open to other suggestions.

Copy link
Contributor

Choose a reason for hiding this comment

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

I think for future rules github/react is kinda nice?

Copy link
Contributor

Choose a reason for hiding this comment

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

I like having a11y-specific rules! But if it's too early to make that distinction until there are more react rules & accessibility rules, I am fine with this for now.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yeah I'm not sure either... I'm down to keep this for now and revisit later!

@khiga8
Copy link
Contributor Author

khiga8 commented Jul 20, 2022

Hi 👋

This is ready for review. @github/web-systems-reviewers. I plan to follow up on this with a separate PR where we introduce a config that allows mapping Primer components to a tag, allowing them to be linted. So ultimately we want this lint to also catch <Link>

@@ -0,0 +1,68 @@
const {elementType, getProp, getPropValue} = require('jsx-ast-utils')

const bannedLinkText = ['read more', 'here', 'click here', 'learn more', 'more', 'here']

Choose a reason for hiding this comment

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

nit: 'here' is in this list twice.

create(context) {
return {
JSXOpeningElement: node => {
if (elementType(node) !== 'a') return

Choose a reason for hiding this comment

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

In general we will probably use the Link component from @primer/react more often than raw anchor tags, and this check would miss those.

I don't think we can catch all of the possible cases just using a linter, but it might be more thorough to apply this check to any element with an href prop. That will at least catch the cases where we have components that are thin wrappers around anchor tags.

Copy link
Contributor Author

@khiga8 khiga8 Jul 20, 2022

Choose a reason for hiding this comment

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

I have a follow up PR to address this lack of support for linting custom components. I'd love your feedback there -- #283.

@khiga8 khiga8 merged commit 70a4fb0 into main Jul 21, 2022
@khiga8 khiga8 deleted the kh-add-a11y branch July 21, 2022 14:31
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

6 participants