Skip to content

Commit 75ae0a5

Browse files
authored
Export enforce-button-for-link-with-no-href rule, plus some minor tidying (#461)
* add missing dash to rule name * include enforce-button-for-link-with-no-href in exported rules * sort list of exported rules * add docs for enforce-button-for-link-with-no-href rule * rename new-color-css-vars docs to match rule name * link all docs in readme * add changeset * run format
1 parent 83ef140 commit 75ae0a5

File tree

7 files changed

+82
-22
lines changed

7 files changed

+82
-22
lines changed

.changeset/tough-parts-sin.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'eslint-plugin-primer-react': patch
3+
---
4+
5+
Export `enforce-button-for-link-with-no-href` rule, which flags `Link` components which don't have a `href`.

README.md

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -31,13 +31,26 @@ ESLint rules for Primer React
3131

3232
## Rules
3333

34-
- [direct-slot-children](https://github.com/primer/eslint-plugin-primer-react/blob/main/docs/rules/direct-slot-children.md)
35-
- [no-system-props](https://github.com/primer/eslint-plugin-primer-react/blob/main/docs/rules/no-system-props.md)
36-
- [new-css-color-vars](https://github.com/primer/eslint-plugin-primer-react/blob/main/docs/rules/new-css-color-vars.md)
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)
3934
- [a11y-explicit-heading](https://github.com/primer/eslint-plugin-primer-react/blob/main/docs/rules/a11y-explicit-heading.md)
4035
- [a11y-link-in-text-block](https://github.com/primer/eslint-plugin-primer-react/blob/main/docs/rules/a11y-link-in-text-block.md)
36+
- [a11y-no-duplicate-form-labels](https://github.com/primer/eslint-plugin-primer-react/blob/main/docs/rules/a11y-no-duplicate-form-labels.md)
37+
- [a11y-no-title-usage](https://github.com/primer/eslint-plugin-primer-react/blob/main/docs/rules/a11y-no-title-usage.md)
4138
- [a11y-remove-disable-tooltip](https://github.com/primer/eslint-plugin-primer-react/blob/main/docs/rules/a11y-remove-disable-tooltip.md)
39+
- [a11y-tooltip-interactive-trigger](https://github.com/primer/eslint-plugin-primer-react/blob/main/docs/rules/a11y-tooltip-interactive-trigger.md)
4240
- [a11y-use-accessible-tooltip](https://github.com/primer/eslint-plugin-primer-react/blob/main/docs/rules/a11y-use-accessible-tooltip.md)
41+
- [direct-slot-children](https://github.com/primer/eslint-plugin-primer-react/blob/main/docs/rules/direct-slot-children.md)
42+
- [enforce-button-for-link-with-no-href](https://github.com/primer/eslint-plugin-primer-react/blob/main/docs/rules/enforce-button-for-link-with-no-href.md)
43+
- [enforce-css-module-default-import](https://github.com/primer/eslint-plugin-primer-react/blob/main/docs/rules/enforce-css-module-default-import.md)
44+
- [enforce-css-module-identifier-casing](https://github.com/primer/eslint-plugin-primer-react/blob/main/docs/rules/enforce-css-module-identifier-casing.md)
45+
- [new-color-css-vars](https://github.com/primer/eslint-plugin-primer-react/blob/main/docs/rules/new-color-css-vars.md)
46+
- [no-deprecated-entrypoints](https://github.com/primer/eslint-plugin-primer-react/blob/main/docs/rules/no-deprecated-entrypoints.md)
4347
- [no-deprecated-experimental-components](https://github.com/primer/eslint-plugin-primer-react/blob/main/docs/rules/no-deprecated-experimental-components.md)
48+
- [no-deprecated-props](https://github.com/primer/eslint-plugin-primer-react/blob/main/docs/rules/no-deprecated-props.md)
49+
- [no-system-props](https://github.com/primer/eslint-plugin-primer-react/blob/main/docs/rules/no-system-props.md)
50+
- [no-unnecessary-components](https://github.com/primer/eslint-plugin-primer-react/blob/main/docs/rules/no-unnecessary-components.md)
51+
- [no-use-responsive-value](https://github.com/primer/eslint-plugin-primer-react/blob/main/docs/rules/no-use-responsive-value.md)
52+
- [no-wildcard-imports](https://github.com/primer/eslint-plugin-primer-react/blob/main/docs/rules/no-wildcard-imports.md)
53+
- [prefer-action-list-item-onselect](https://github.com/primer/eslint-plugin-primer-react/blob/main/docs/rules/prefer-action-list-item-onselect.md)
54+
- [spread-props-first](https://github.com/primer/eslint-plugin-primer-react/blob/main/docs/rules/spread-props-first.md)
55+
- [use-deprecated-from-deprecated](https://github.com/primer/eslint-plugin-primer-react/blob/main/docs/rules/use-deprecated-from-deprecated.md)
56+
- [use-styled-react-import](https://github.com/primer/eslint-plugin-primer-react/blob/main/docs/rules/use-styled-react-import.md)
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
# Enforce Button for Link with No href (enforce-button-for-link-with-no-href)
2+
3+
Primer's `Link` component enables users to navigate between pages. Rendering it without an `href` makes the element behave like a button without the correct semantics, which negatively impacts accessibility. Use the `Button` component to trigger an action, or ensure the `Link` has a valid `href`.
4+
5+
## Rule details
6+
7+
This rule reports any `Link` from `@primer/react` that does not include an `href` prop.
8+
9+
👎 Examples of **incorrect** code for this rule:
10+
11+
```jsx
12+
/* eslint primer-react/enforce-button-for-link-with-no-href: "error" */
13+
import {Link} from '@primer/react'
14+
;<Link onClick={handleClick}>Save changes</Link>
15+
```
16+
17+
```jsx
18+
/* eslint primer-react/enforce-button-for-link-with-no-href: "error" */
19+
import {Link} from '@primer/react'
20+
;<Link className="text-right">Learn more</Link>
21+
```
22+
23+
👍 Examples of **correct** code for this rule:
24+
25+
```jsx
26+
/* eslint primer-react/enforce-button-for-link-with-no-href: "error" */
27+
import {Link} from '@primer/react'
28+
;<Link href="https://primer.style/react">Read the docs</Link>
29+
```
30+
31+
```jsx
32+
/* eslint primer-react/enforce-button-for-link-with-no-href: "error" */
33+
import {Button, Link} from '@primer/react'
34+
35+
<Button onClick={handleClick}>Save changes</Button>
36+
<Link href={issueUrl}>View issue</Link>
37+
```
38+
39+
## Options
40+
41+
This rule has no options.
File renamed without changes.

src/index.js

Lines changed: 16 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,28 @@
11
module.exports = {
22
rules: {
3-
'direct-slot-children': require('./rules/direct-slot-children'),
4-
'no-deprecated-entrypoints': require('./rules/no-deprecated-entrypoints'),
5-
'no-system-props': require('./rules/no-system-props'),
6-
'no-deprecated-experimental-components': require('./rules/no-deprecated-experimental-components'),
7-
'a11y-tooltip-interactive-trigger': require('./rules/a11y-tooltip-interactive-trigger'),
8-
'new-color-css-vars': require('./rules/new-color-css-vars'),
93
'a11y-explicit-heading': require('./rules/a11y-explicit-heading'),
10-
'no-deprecated-props': require('./rules/no-deprecated-props'),
114
'a11y-link-in-text-block': require('./rules/a11y-link-in-text-block'),
5+
'a11y-no-duplicate-form-labels': require('./rules/a11y-no-duplicate-form-labels'),
6+
'a11y-no-title-usage': require('./rules/a11y-no-title-usage'),
127
'a11y-remove-disable-tooltip': require('./rules/a11y-remove-disable-tooltip'),
8+
'a11y-tooltip-interactive-trigger': require('./rules/a11y-tooltip-interactive-trigger'),
139
'a11y-use-accessible-tooltip': require('./rules/a11y-use-accessible-tooltip'),
14-
'a11y-no-title-usage': require('./rules/a11y-no-title-usage'),
15-
'a11y-no-duplicate-form-labels': require('./rules/a11y-no-duplicate-form-labels'),
16-
'use-deprecated-from-deprecated': require('./rules/use-deprecated-from-deprecated'),
17-
'no-wildcard-imports': require('./rules/no-wildcard-imports'),
10+
'direct-slot-children': require('./rules/direct-slot-children'),
11+
'enforce-button-for-link-with-no-href': require('./rules/enforce-button-for-link-with-no-href'),
12+
'enforce-css-module-default-import': require('./rules/enforce-css-module-default-import'),
13+
'enforce-css-module-identifier-casing': require('./rules/enforce-css-module-identifier-casing'),
14+
'new-color-css-vars': require('./rules/new-color-css-vars'),
15+
'no-deprecated-entrypoints': require('./rules/no-deprecated-entrypoints'),
16+
'no-deprecated-experimental-components': require('./rules/no-deprecated-experimental-components'),
17+
'no-deprecated-props': require('./rules/no-deprecated-props'),
18+
'no-system-props': require('./rules/no-system-props'),
1819
'no-unnecessary-components': require('./rules/no-unnecessary-components'),
20+
'no-use-responsive-value': require('./rules/no-use-responsive-value'),
21+
'no-wildcard-imports': require('./rules/no-wildcard-imports'),
1922
'prefer-action-list-item-onselect': require('./rules/prefer-action-list-item-onselect'),
20-
'enforce-css-module-identifier-casing': require('./rules/enforce-css-module-identifier-casing'),
21-
'enforce-css-module-default-import': require('./rules/enforce-css-module-default-import'),
22-
'use-styled-react-import': require('./rules/use-styled-react-import'),
2323
'spread-props-first': require('./rules/spread-props-first'),
24-
'no-use-responsive-value': require('./rules/no-use-responsive-value'),
24+
'use-deprecated-from-deprecated': require('./rules/use-deprecated-from-deprecated'),
25+
'use-styled-react-import': require('./rules/use-styled-react-import'),
2526
},
2627
configs: {
2728
recommended: require('./configs/recommended'),

src/rules/__tests__/enforce-button-for-link-with-nohref.test.js renamed to src/rules/__tests__/enforce-button-for-link-with-no-href.test.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
const rule = require('../enforce-button-for-link-with-nohref')
1+
const rule = require('../enforce-button-for-link-with-no-href')
22
const {RuleTester} = require('eslint')
33

44
const ruleTester = new RuleTester({
@@ -13,7 +13,7 @@ const ruleTester = new RuleTester({
1313
},
1414
})
1515

16-
ruleTester.run('enforce-button-for-link-with-nohref', rule, {
16+
ruleTester.run('enforce-button-for-link-with-no-href', rule, {
1717
valid: [
1818
// Link with href attribute
1919
`import {Link} from '@primer/react';
File renamed without changes.

0 commit comments

Comments
 (0)