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 link-type styling recommendation to anchor-is-valid #486

Merged
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
6 changes: 3 additions & 3 deletions __tests__/src/rules/anchor-is-valid-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,11 @@ import rule from '../../../src/rules/anchor-is-valid';

const ruleTester = new RuleTester();

const preferButtonErrorMessage = 'Anchor used as a button. Anchors are primarily expected to navigate. Use the button element instead.';
const preferButtonErrorMessage = 'Anchor used as a button. Anchors are primarily expected to navigate. Use the button element instead. Learn more: https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/anchor-is-valid.md';

const noHrefErrorMessage = 'The href attribute is required on an anchor. Provide a valid, navigable address as the href value.';
const noHrefErrorMessage = 'The href attribute is required for an anchor to be keyboard accessible. Provide a valid, navigable address as the href value. If you cannot provide an href, but still need the element to resemble a link, use a button and change it with appropriate styles. Learn more: https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/anchor-is-valid.md';

const invalidHrefErrorMessage = 'The href attribute requires a valid address. Provide a valid, navigable address as the href value.';
const invalidHrefErrorMessage = 'The href attribute requires a valid value to be accessible. Provide a valid, navigable address as the href value. If you cannot provide a valid href, but still need the element to resemble a link, use a button and change it with appropriate styles. Learn more: https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/anchor-is-valid.md';

const preferButtonexpectedError = {
message: preferButtonErrorMessage,
Expand Down
41 changes: 41 additions & 0 deletions docs/rules/anchor-is-valid.md
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,47 @@ If you need to create an interface element that the user can mouse over or mouse

In the example immediately above an `onClick` event handler was added to provide the same experience mouse users enjoy to keyboard-only and touch-screen users. Never fully rely on mouse events alone to expose functionality.

### Case: I understand the previous cases but still need an element resembling a link that is purely clickable

We recommend, without reserve, that elements resembling anchors should navigate. This will provide a superior user experience to a larger group of users out there.

However, we understand that developers are not always in total control of the visual design of web applications. In cases where it is imperative to provide an element resembling an anchor that purely acts as a click target with no navigation as result, we would like to recommend a compromise.

Again change the element to a `<button>`:

```jsx
<button
Copy link
Member

Choose a reason for hiding this comment

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

all <button> elements should have an explicit type; let's be sure our examples do too. In this case, type="button" (or else it'll be a submit button).

Copy link
Contributor Author

Choose a reason for hiding this comment

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

100%

type="button"
className="link-button"
ljharb marked this conversation as resolved.
Show resolved Hide resolved
onClick={() => this.setState({showSomething: true})}>
Press me, I look like a link
</button>
```

Then use styling to change its appearance to that of a link:

```css
.link-button {
background-color: transparent;
border: none;
cursor: pointer;
text-decoration: underline;
display: inline;
margin: 0;
padding: 0;
}

.link-button:hover,
.link-button:focus {
text-decoration: none;
}
```

This button element can now also be used inline in text.

Once again we stress that this is an inferior implementation and some users will encounter difficulty to use your website, however, it will allow a larger group of people to interact with your website than the alternative of ignoring the rule's warning.


### References
1. [WebAIM - Introduction to Links and Hypertext](http://webaim.org/techniques/hypertext/)
1. [Links vs. Buttons in Modern Web Applications](https://marcysutton.com/links-vs-buttons-in-modern-web-applications/)
Expand Down
6 changes: 3 additions & 3 deletions src/rules/anchor-is-valid.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,11 @@ import { generateObjSchema, arraySchema, enumArraySchema } from '../util/schemas

const allAspects = ['noHref', 'invalidHref', 'preferButton'];

const preferButtonErrorMessage = 'Anchor used as a button. Anchors are primarily expected to navigate. Use the button element instead.';
const preferButtonErrorMessage = 'Anchor used as a button. Anchors are primarily expected to navigate. Use the button element instead. Learn more: https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/anchor-is-valid.md';

const noHrefErrorMessage = 'The href attribute is required on an anchor. Provide a valid, navigable address as the href value.';
const noHrefErrorMessage = 'The href attribute is required for an anchor to be keyboard accessible. Provide a valid, navigable address as the href value. If you cannot provide an href, but still need the element to resemble a link, use a button and change it with appropriate styles. Learn more: https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/anchor-is-valid.md';

const invalidHrefErrorMessage = 'The href attribute requires a valid address. Provide a valid, navigable address as the href value.';
const invalidHrefErrorMessage = 'The href attribute requires a valid value to be accessible. Provide a valid, navigable address as the href value. If you cannot provide a valid href, but still need the element to resemble a link, use a button and change it with appropriate styles. Learn more: https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/anchor-is-valid.md';
Copy link

Choose a reason for hiding this comment

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

Could we run these links through a url shortener? 😄 i.e. https://goo.gl/s89kbn

Copy link
Member

Choose a reason for hiding this comment

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

what's the benefit of that, versus the loss of clarity on where it will redirect to?

Copy link

Choose a reason for hiding this comment

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

It'd reduce console noise for users who run into this a lot but know how to handle it.

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 can do this, if required :-)

@ljharb Do you think shortening the link will cause enough clarity loss not to cut the verbosity?

Copy link

Choose a reason for hiding this comment

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

We could use an aliased shortlink for improved clarity, e.g. https://tinyurl.com/anchor-is-valid

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Hey everyone, is this a will or won't do. I am still more than happy to do the PR. We could use Git.io but then the url will no longer be readable at all.

Copy link
Member

Choose a reason for hiding this comment

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

I’m still leaning towards “no”

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@Timer, as you raised it, is this something you can live with in CRA? Would be awesome to keep this rule alive in there 😄

Copy link

Choose a reason for hiding this comment

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

Yeah, we'll probably just replace the link ourselves in the output formatter. Thanks!

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Awesome!


const schema = generateObjSchema({
components: arraySchema,
Expand Down