eslint-plugin-jsx-a11y icon indicating copy to clipboard operation
eslint-plugin-jsx-a11y copied to clipboard

`anchor-has-content` throwing false negatives

Open bmbrandx opened this issue 3 years ago • 11 comments

The anchor-has-content rule is throwing an error even though the anchor in question clearly has content. This is happening on nearly all links that have hard-coded content. The only way to resolve the issue is by adding brackes { } around the offending content. Any support on this issue would be fantastic as enabling this rule is very important.

Failure: <a> This is a test </a>

Success: <a>{ This is a test }</a>

Examples of failures from our codebase: Screen Shot 2021-03-22 at 2 31 05 PM

bmbrandx avatar Mar 22 '21 21:03 bmbrandx

This definitely seems like a bug. Can you confirm the versions you have installed of node, eslint, and eslint-plugin-jsx-a11y?

ljharb avatar Mar 23 '21 01:03 ljharb

I have the same issue - it only errors if you explicitly set onClick

node v16.0.0 eslint: v7.28.0 eslint-plugin-jsx-a11y v6.4.1

skworden avatar Jun 18 '21 00:06 skworden

Why would you use <a> solely for onClick? That's what <button type="button"> is for.

ljharb avatar Jun 18 '21 05:06 ljharb

We allow prop spreading in components that are HTML so href and other props are not explicitly set but are required via a React/vanilla type HTMLProps<HTMLAnchorElement>.

og code <a {...props} onClick={onClick}/>

Potential fixes we identified are

  • Remove the explicitly set onClick prop (not an option for us)
  • Explicitly set onClick and href (destructor href and spread the rest of the props - option we chose)
  • Manually ignore the rule

fix <a {...rest} href={href} onClick={onClick}/>

skworden avatar Jun 19 '21 06:06 skworden

@lifedup you should never render an <a> tag without an explicit href, and without explicit children.

iow, <a href={props.href} onClick={onClick} {...props}>{props.children}</a> seems like it'd solve your issue.

ljharb avatar Jun 19 '21 06:06 ljharb

I hear you and I wish it was that b&w but we use next.js and its next/link component. We also explicitly set the children and other props but that was for brevity . My previous post is our work around that does the job.

It wasn't logical to us that you can spread all the props and not explicitly set any of them without error on an anchor tag, but if you explicitly set onClick you must also explicitly set href and can't spread it like the rest of the props.

skworden avatar Jun 19 '21 07:06 skworden

Linting is static analysis. It can’t do anything with spread props - it’s just a limitation of the language.

so, you can either discard brevity in favor of correctness, or you can disable this lint rule with an override comment. There’s really no other choice.

ljharb avatar Jun 19 '21 07:06 ljharb

what about anchors, like <a id="main" /> which used for anchor navigation?

For example I have a section on the screen which starts with such an anchor, and then somewhere else on the page (side menu or 'back to top' link for example) I have a link to this anchor like <a href='#main'>some text</a>.

Should I put an empty href attribute and empty content (or nonbreakable space like &nbsp;) for such anchor?

alexiusp avatar Jul 27 '22 14:07 alexiusp

@alexiusp for the <a id="main">, you don't need the ID to be an a tag - you can link to any ID on the page. So, put the ID on the actual content container you're trying to link to.

ljharb avatar Aug 09 '22 23:08 ljharb

Screenshot 2023-01-17 alle 16 35 55

I also have this issue in a storybook mdx file

smellai avatar Jan 17 '23 15:01 smellai

@smellai that definitely seems wrong; those are real links with content and hrefs. I'm not familiar with mdx tho; can you file a separate issue for that, and include info about your eslint parser and config?

ljharb avatar Jan 17 '23 17:01 ljharb