eslint-plugin-primer-react 5.2.1-rc.61b0e36 → 5.3.0-rc.e240e9d

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,9 +1,17 @@
1
1
  # eslint-plugin-primer-react
2
2
 
3
+ ## 5.3.0
4
+
5
+ ### Minor Changes
6
+
7
+ - [#185](https://github.com/primer/eslint-plugin-primer-react/pull/185) [`fea642d`](https://github.com/primer/eslint-plugin-primer-react/commit/fea642d79982e36729262ec55d6e291780ca6160) Thanks [@broccolinisoup](https://github.com/broccolinisoup)! - Add a rule that warns against removing `unsafeDisableTooltip` prop
8
+
3
9
  ## 5.2.1
4
10
 
5
11
  ### Patch Changes
6
12
 
13
+ - [#195](https://github.com/primer/eslint-plugin-primer-react/pull/195) [`ccc2e99`](https://github.com/primer/eslint-plugin-primer-react/commit/ccc2e995a3f46bb4842468188b91c0bd641da390) Thanks [@khiga8](https://github.com/khiga8)! - Clean up docs for link lint rule
14
+
7
15
  - [#193](https://github.com/primer/eslint-plugin-primer-react/pull/193) [`5fc19f6`](https://github.com/primer/eslint-plugin-primer-react/commit/5fc19f63a4916add7b3c335ac661119c50af17af) Thanks [@khiga8](https://github.com/khiga8)! - Update link lint rule to skip Link with className
8
16
 
9
17
  ## 5.2.0
package/README.md CHANGED
@@ -33,7 +33,9 @@ ESLint rules for Primer React
33
33
 
34
34
  - [direct-slot-children](https://github.com/primer/eslint-plugin-primer-react/blob/main/docs/rules/direct-slot-children.md)
35
35
  - [no-system-props](https://github.com/primer/eslint-plugin-primer-react/blob/main/docs/rules/no-system-props.md)
36
- - [a11y-tooltip-interactive-trigger](https://github.com/primer/eslint-plugin-primer-react/blob/main/docs/rules/a11y-tooltip-interactive-trigger.md)
37
- - [a11y-explicit-heading](https://github.com/primer/eslint-plugin-primer-react/blob/main/docs/rules/a11y-explicit-heading.md)
38
36
  - [new-css-color-vars](https://github.com/primer/eslint-plugin-primer-react/blob/main/docs/rules/new-css-color-vars.md)
39
37
  - [no-deprecated-props](https://github.com/primer/eslint-plugin-primer-react/blob/main/docs/rules/no-deprecated-props.md)
38
+ - [a11y-tooltip-interactive-trigger](https://github.com/primer/eslint-plugin-primer-react/blob/main/docs/rules/a11y-tooltip-interactive-trigger.md)
39
+ - [a11y-explicit-heading](https://github.com/primer/eslint-plugin-primer-react/blob/main/docs/rules/a11y-explicit-heading.md)
40
+ - [a11y-link-in-text-block](https://github.com/primer/eslint-plugin-primer-react/blob/main/docs/rules/a11y-link-in-text-block.md)
41
+ - [a11y-remove-disable-tooltip](https://github.com/primer/eslint-plugin-primer-react/blob/main/docs/rules/a11y-remove-disable-tooltip.md)
@@ -1,22 +1,25 @@
1
- ## Require `inline` prop on `<Link>` component inside a text block
1
+ # EXPERIMENTAL: Require `inline` prop on `<Link>` in text block
2
2
 
3
- The `Link` component should have the `inline` prop when it is used inside of a text block.
3
+ This is an experimental rule. If you suspect any false positives reported by this rule, please file an issue so we can make this rule better.
4
4
 
5
5
  ## Rule Details
6
6
 
7
- This rule enforces setting `inline` on the `<Link>` component when a `<Link>` is detected inside of a text block without distiguishable styling.
7
+ The `Link` component should have the `inline` prop when it is used within a text block and has no styles (aside from color) to distinguish itself from surrounding plain text.
8
8
 
9
- The lint rule will essentially flag any `<Link>` without the `inline` property (equal to `true`) detected with string nodes on either side.
9
+ Related: [WCAG 1.4.1 Use of Color issues](https://www.w3.org/WAI/WCAG21/Understanding/use-of-color.html)
10
10
 
11
- This rule will not catch all instances of link in text block due to the limitations of static analysis, so be sure to also have in-browser checks in place such as the [link-in-text-block Axe rule](https://dequeuniversity.com/rules/axe/4.9/link-in-text-block) for additional coverage.
11
+ The lint rule will flag any `<Link>` without the `inline` property (equal to `true`) detected with string nodes on either side.
12
12
 
13
- The edge cases that the linter skips to avoid false positives will include:
13
+ There are certain edge cases that the linter skips to avoid false positives including:
14
14
 
15
+ - `<Link className="...">` because there may be distinguishing styles applied.
15
16
  - `<Link sx={{fontWeight:...}}>` or `<Link sx={{fontFamily:...}}>` because these technically may provide sufficient distinguishing styling.
16
17
  - `<Link>` where the only adjacent text is a period, since that can't really be considered a text block.
17
18
  - `<Link>` where the children is a JSX component, rather than a string literal, because then it might be an icon link rather than a text link.
18
19
  - `<Link>` that are nested inside of headings as these have often been breadcrumbs.
19
20
 
21
+ This rule will not catch all instances of link in text block due to the limitations of static analysis, so be sure to also have in-browser checks in place such as the [link-in-text-block Axe rule](https://dequeuniversity.com/rules/axe/4.9/link-in-text-block) for additional coverage.
22
+
20
23
  👎 Examples of **incorrect** code for this rule
21
24
 
22
25
  ```jsx
@@ -93,8 +96,18 @@ function ExampleComponent() {
93
96
  }
94
97
  ```
95
98
 
99
+ This rule will skip `Link`s with a `className`.
100
+
101
+ ```jsx
102
+ function ExampleComponent() {
103
+ return (
104
+ Learn more at <Link className={styles.someDistinguishingStyle}>GitHub</Link>
105
+ )
106
+ }
107
+ ```
108
+
96
109
  ## Options
97
110
 
98
111
  - `skipImportCheck` (default: `false`)
99
112
 
100
- By default, the `a11y-explicit-heading` rule will only check for `<Heading>` components imported directly from `@primer/react`. You can disable this behavior by setting `skipImportCheck` to `true`.
113
+ By default, the `a11y-link-in-text-block` rule will only check for `<Link>` components imported directly from `@primer/react`. You can disable this behavior by setting `skipImportCheck` to `true`.
@@ -0,0 +1,25 @@
1
+ ## Rule Details
2
+
3
+ This rule enforces to remove the `unsafeDisableTooltip` from `IconButton` component so that they have a tooltip by default. `unsafeDisableTooltip` prop is created for an incremental migration and should be removed once all icon buttons have a tooltip.
4
+
5
+ 👎 Examples of **incorrect** code for this rule:
6
+
7
+ ```jsx
8
+ import {IconButton} from '@primer/react'
9
+
10
+ const App = () => (
11
+ <IconButton icon={SearchIcon} aria-label="Search" unsafeDisableTooltip />
12
+ // OR
13
+ <IconButton icon={SearchIcon} aria-label="Search" unsafeDisableTooltip={true} />
14
+ // OR
15
+ <IconButton icon={SearchIcon} aria-label="Search" unsafeDisableTooltip={false} /> // This is incorrect because it should be removed
16
+ )
17
+ ```
18
+
19
+ 👍 Examples of **correct** code for this rule:
20
+
21
+ ```jsx
22
+ import {IconButton} from '@primer/react'
23
+
24
+ const App = () => <IconButton icon={SearchIcon} aria-label="Search" />
25
+ ```
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "eslint-plugin-primer-react",
3
- "version": "5.2.1-rc.61b0e36",
3
+ "version": "5.3.0-rc.e240e9d",
4
4
  "description": "ESLint rules for Primer React",
5
5
  "main": "src/index.js",
6
6
  "scripts": {
@@ -16,6 +16,7 @@ module.exports = {
16
16
  'primer-react/new-color-css-vars': 'error',
17
17
  'primer-react/a11y-explicit-heading': 'error',
18
18
  'primer-react/no-deprecated-props': 'warn',
19
+ 'primer-react/a11y-remove-disable-tooltip': 'error',
19
20
  },
20
21
  settings: {
21
22
  github: {
package/src/index.js CHANGED
@@ -8,6 +8,7 @@ module.exports = {
8
8
  'a11y-explicit-heading': require('./rules/a11y-explicit-heading'),
9
9
  'no-deprecated-props': require('./rules/no-deprecated-props'),
10
10
  'a11y-link-in-text-block': require('./rules/a11y-link-in-text-block'),
11
+ 'a11y-remove-disable-tooltip': require('./rules/a11y-remove-disable-tooltip'),
11
12
  },
12
13
  configs: {
13
14
  recommended: require('./configs/recommended'),
@@ -0,0 +1,50 @@
1
+ 'use strict'
2
+
3
+ const {RuleTester} = require('eslint')
4
+ const rule = require('../a11y-remove-disable-tooltip')
5
+
6
+ const ruleTester = new RuleTester({
7
+ parserOptions: {
8
+ ecmaVersion: 'latest',
9
+ sourceType: 'module',
10
+ ecmaFeatures: {
11
+ jsx: true,
12
+ },
13
+ },
14
+ })
15
+
16
+ ruleTester.run('a11y-remove-disable-tooltip', rule, {
17
+ valid: [
18
+ `import {IconButton} from '@primer/react';
19
+ <IconButton icon={SearchIcon} aria-label="Search" />`,
20
+ ],
21
+ invalid: [
22
+ {
23
+ code: `<IconButton icon={SearchIcon} aria-label="Search" unsafeDisableTooltip />`,
24
+ output: `<IconButton icon={SearchIcon} aria-label="Search" />`,
25
+ errors: [
26
+ {
27
+ messageId: 'removeDisableTooltipProp',
28
+ },
29
+ ],
30
+ },
31
+ {
32
+ code: `<IconButton icon={SearchIcon} aria-label="Search" unsafeDisableTooltip={true} />`,
33
+ output: `<IconButton icon={SearchIcon} aria-label="Search" />`,
34
+ errors: [
35
+ {
36
+ messageId: 'removeDisableTooltipProp',
37
+ },
38
+ ],
39
+ },
40
+ {
41
+ code: `<IconButton icon={SearchIcon} aria-label="Search" unsafeDisableTooltip={false} />`,
42
+ output: `<IconButton icon={SearchIcon} aria-label="Search" />`,
43
+ errors: [
44
+ {
45
+ messageId: 'removeDisableTooltipProp',
46
+ },
47
+ ],
48
+ },
49
+ ],
50
+ })
@@ -4,6 +4,9 @@ const {getJSXOpeningElementAttribute} = require('../utils/get-jsx-opening-elemen
4
4
 
5
5
  module.exports = {
6
6
  meta: {
7
+ docs: {
8
+ url: require('../url')(module),
9
+ },
7
10
  type: 'problem',
8
11
  schema: [
9
12
  {
@@ -15,7 +18,8 @@ module.exports = {
15
18
  },
16
19
  ],
17
20
  messages: {
18
- linkInTextBlock: '<Link>s that are used within a text block should have the inline prop.',
21
+ linkInTextBlock:
22
+ 'Links should have the inline prop if it appear in a text block and only uses color to distinguish itself from surrounding text.',
19
23
  },
20
24
  },
21
25
  create(context) {
@@ -0,0 +1,47 @@
1
+ 'use strict'
2
+ const {getJSXOpeningElementAttribute} = require('../utils/get-jsx-opening-element-attribute')
3
+ const {getJSXOpeningElementName} = require('../utils/get-jsx-opening-element-name')
4
+
5
+ /**
6
+ * @type {import('eslint').Rule.RuleModule}
7
+ */
8
+ module.exports = {
9
+ meta: {
10
+ type: 'error',
11
+ docs: {
12
+ description:
13
+ 'Icon buttons should have tooltip by default. Please remove `unsafeDisableTooltip` prop from `IconButton` component to enable the tooltip and help making icon button more accessible.',
14
+ recommended: true,
15
+ },
16
+ fixable: 'code',
17
+ schema: [],
18
+ messages: {
19
+ removeDisableTooltipProp:
20
+ 'Please remove `unsafeDisableTooltip` prop from `IconButton` component to enable the tooltip and help make icon button more accessible.',
21
+ },
22
+ },
23
+ create(context) {
24
+ return {
25
+ JSXOpeningElement(node) {
26
+ const openingElName = getJSXOpeningElementName(node)
27
+ if (openingElName !== 'IconButton') {
28
+ return
29
+ }
30
+ const unsafeDisableTooltip = getJSXOpeningElementAttribute(node, 'unsafeDisableTooltip')
31
+ if (unsafeDisableTooltip !== undefined) {
32
+ context.report({
33
+ node,
34
+ messageId: 'removeDisableTooltipProp',
35
+ fix(fixer) {
36
+ const start = unsafeDisableTooltip.range[0]
37
+ const end = unsafeDisableTooltip.range[1]
38
+ return [
39
+ fixer.removeRange([start - 1, end]), // remove the space before unsafeDisableTooltip as well
40
+ ]
41
+ },
42
+ })
43
+ }
44
+ },
45
+ }
46
+ },
47
+ }