when image tag role be set button jsx-a11y show warning - reactjs

I need make image tag clickable, but I get a warning by jsx-a11y, how do I fixed it, I already read no-noninteractive-element-interactions, but I do not wanna wrap other div tag around img tag, because it will make a redundancy tag, so does any other way to fix this warning?
The warning is [eslint] Non-interactive elements should not be assigned interactive roles.
and my code is
<img
styleName="pic-id-code"
src={picCodeImgSrc}
alt="pic id code"
onClick={this.refreshPicCodeImg}
onKeyPress={this.handleKeyPress}
role="button"
tabIndex="0"
/>

You should use <input type="image" /> for your use case, it is semantically correct and you won't need to add role or tabindex or any other ARIA tags to make it work and accessible.
There is a caveat as this doesn't actually return to normal state after click and remains focused so you need to call blur after your onClick logic. Here's the simple demo I made few days back to remove focus on click.

You can disable eslint for a specify line like this
// eslint-disable-next-line THE-RULE-HERE
<img
styleName="pic-id-code"
src={picCodeImgSrc}
alt="pic id code"
onClick={this.refreshPicCodeImg}
onKeyPress={this.handleKeyPress}
role="button"
tabIndex="0"
/>
Not sure what exactly your rule is but try this
// eslint-disable-next-line jsx-a11y/no-noninteractive-element-interactions
or
// eslint-disable-next-line no-noninteractive-element-interactions
Update after OP comment
... but no work in react jsx
Try this
<img
styleName="pic-id-code"
src={picCodeImgSrc}
alt="pic id code"
// eslint-disable-next-line jsx-a11y/no-noninteractive-element-interactions
onClick={this.refreshPicCodeImg}
// eslint-disable-next-line jsx-a11y/no-noninteractive-element-interactions
onKeyPress={this.handleKeyPress}
// eslint-disable-next-line jsx-a11y/no-noninteractive-element-interactions
role="button"
tabIndex="0"
/>
onClick and oneKeyPress on img will also trigger warnings.

Related

href attribute is required in combination with history react module

I use the history React module to manage the session history, and have links such as:
<a
className="edit"
onClick={() => {
history.push(`/user/${this.props.match.params.id}/${i.slug}`);
}}
>
Edit User
</a>
This generates the following warning from ESLint:
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/jsx-eslint/eslint-plugin-jsx-a11y/blob/HEAD/docs/rules/anchor-is-valid.md jsx-a11y/anchor-is-valid
Is there a way to resolve this warning without turning the hyperlink into a button?
(given the complexity of the CSS going on inside the repository, converting it to a button would be a lot of work.)
If I just add href, like below, then the ESLint warning is solved. But can the history module then still do its job properly?
<a
className="edit"
href={`/user/${this.props.match.params.id}/${i.slug}`} //extra line
onClick={() => {
history.push(`/user/${this.props.match.params.id}/${i.slug}`);
}}
>
Edit User
</a>
If using href is necessary you can do something like : href="javascript:void(0)"

How to Disable Images in React

I am using a set if images in a row. There is a text box input above these images and based on the input i need to enable/disable images?
How to do this in React.
I tried adding "disable" to image tag and disabled=true but both didn't work.
const IBox = props =>
<div style={props.styles.imageContainer} >
<img id="image1" src={require('../../../public/images/image1.jpg')} alt = "Image1" /><span > </span>
<img id="image2" src={require('../../../public/images/image2.jpg')} alt ="Image2" /><span> </span>
<img id="image3" src={require('../../../public/images/image3.jpg')} alt ="Image3" /><span> </span>
<img id="image4" src={require('../../../public/images/image4.jpg')} alt ="Image4"/>
</div>
export default IBox;
There is no such thing as "disabling" images. You can only disable form elements, as they are the only interactive html elements. See w3c specification to see which items can be disabled exactly.
That is unless you write your own custom definition for disabling images. For example, you could add a class disabled to the image, and style that class to be greyed out, using CSS.
You could also combine CSS with WebComponents to have an element that with a disabled attribute. You could style its disabled style.
See also docs for the <img /> tag.
If you mean hide/show.. you simply may use state to disable your image i.e.
{this.state.img1 && <img id="image1" src={require('../../../public/images/image1.jpg')} alt = "Image1" />}
if by disable you mean to make it like grey, low opacity,etc... you may use an state :
style= this.state.disable? {{style_disable}}: {{style_enable}}
Use <input /> instead of <img /> as in this example.
You can provide the same functionality with the type="image" attribute. This way you can use the disabled attribute.
<input
type="image"
disabled={disabled}
/>

How to fix 'Static HTML elements with event handlers require a role.'?

My reactjs styledcomponent contains this code:
<a styling="link" onClick={() => this.gotoLink()}>
<SomeComponent />
</a>
This works fine but the eslint is complaining:
Static HTML elements with event handlers require a role.
How can I fix this error?
you need to add a role props in your a tag to avoid this warning, for example a button
<a role = "button" styling="link" onClick={() => this.gotoLink()}>
<SomeComponent />
</a>
I guess it is because the HREF props is missing in your anchor tag (not sure)
In my case, I used aria-hidden="true", then I was able to commit.
Before:
<i className="pwdicon" onClick={togglePasswordVisiblity} >
After I updated with aria-hidden:
<i className="pwdicon" onClick={togglePasswordVisiblity} aria-hidden="true" >
My problem was resolved.
Reference Link : https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/blob/master/docs/rules/click-events-have-key-events.md
The earlier answers do give specific examples, what I was missing is a list of roles.
If someone is looking for other roles, a partial list is listed here.
An example of a missing role is tab which I needed.
Edit: per the comment request, my personal error was solved by adding role, but I was missing a list of allowed roles, see above for a partial list and a more complete (or possibly complete) list here, thanks to the comment by Caiof.
You need to set the role explicitly. So, try the next code:
<a role="button" styling="link" onClick={this.gotoLink}>
<SomeComponent />
</a>
Also, as you can see I've modified the onClick handler by replacing arrow function on regular declaration. It would reduce annoying and expensive calculations.
just add aria-hidden to it
<a aria-hidden styling="link" onClick={() => this.gotoLink()}>
<SomeComponent />
</a>
Just need to add the 'aria-hidden' attribute, like this:
<div onClick={handleClickCollectionCard} aria-hidden="true">

Material UI Chip-input's "hintText" is not working

I have a ChipInput like this. I want to show a hint text when it's empty.
<div className={classes.headline}>
<ChipInput
hintText='Type anything'
onChange={this.handleTagChange}
/>
</div>
But my browser gives this warning.
Warning: React does not recognize the hintText prop on a DOM
element. If you intentionally want it to appear in the DOM as a custom
attribute, spell it as lowercase hinttext instead. If you
accidentally passed it from a parent component, remove it from the DOM
element.
As per the ChipInput Readme, it should work. Am I missing something here?
Had a look at the code and found placeholder which worked!!!
<div className={classes.headline}>
<ChipInput
placeholder='Type anything'
onChange={this.handleTagChange}
/>
</div>

How to work around jsx-a11y/no-static-element-interactions restriction?

I used the following jsx to construct an entry in a FAQ table:
<li key={faqKey} className={styles.entry} onClick={handleExpandFn}>
<div>
<span className={`icon-next ${questionClassname}`} />
<span className={styles['question-text']}>{faqEntry.question}</span>
</div>
{faqEntry.answer}
</li>
The idea is that when a user click on the entry, it will toggle the open state of the entry. In the other word, when a user clicks on an open FAQ entry, it will close it. Otherwise it will open it.
However the li tag triggers this eslint violation: Visible, non-interactive elements should not have mouse or keyboard event listeners jsx-a11y/no-static-element-interactions
Unfortunately I don't think there is alternative way to the above html markup.
Since it is jsx, it also does not allow override such as // eslint-disable-line jsx-a11y/no-static-element-interactions (The inline comment will be printed out to the web page)
So how I can work around it? Happy to use different jsx markup or jsx eslint override
For those who are looking for a workaround, use role="presentation" in your tag.
Here's how you could revise the markup to be semantically appropriate and get the onclick off the <li>
<li key={faqKey} className={styles.entry}>
<h3>
<button type='button' onClick={handleExpandFn}>
<span className={`icon-next ${questionClassname}`} />
<span className={styles['question-text']}>{faqEntry.question}</span>
</button>
</h3>
<div className='add_a_panel_class_name_here'>
{faqEntry.answer}
</div>
</li>
So with the above:
the <h3> will make the titles of the FAQs easily searchable by screen reader users that are navigating by headings
placing the <button> inside of the <h3> gives you the appropriate element to attach a click event to (you want to use a button here because you're toggling state. an <a> should be used if you were going to a new page. You also don't need to add a tabindex to a button as they are inherently focusable).
There are some additional steps you'd likely want to implement, using ARIA expanded and controls attributes on the button, but the above should get you to a good base for moving beyond your error.
You could put eslint-disable-line in the jsx
<li // eslint-disable-line jsx-a11y/no-static-element-interactions
key={faqKey}
className={styles.entry}
onClick={handleExpandFn}
>
<div>
<span className={`icon-next ${questionClassname}`} />
<span className={styles['question-text']}>{faqEntry.question}</span>
</div>
{faqEntry.answer}
</li>
Another option, add role='presentation'
<li
key={faqKey}
className={styles.entry}
onClick={handleExpandFn}
role='presentation'
>
<div>
<span className={`icon-next ${questionClassname}`} />
<span className={styles['question-text']}>{faqEntry.question}</span>
</div>
{faqEntry.answer}
</li>
One solution I can remember is to use an anchor element with tab-index.
<a style={{display: 'list-item'}} tabIndex={-42} key={faqKey} className={styles.entry} onClick={handleExpandFn}>
<div>
<span className={`icon-next ${questionClassname}`} />
<span className={styles['question-text']}>{faqEntry.question}</span>
</div>
{faqEntry.answer}
</a>
if you are trying to implement menu using li then the right solution is using role="menuitem" in your li tags.
More details about it: https://w3c.github.io/aria/#menuitem
To overcome or avoid this error in ES Lint.
You can use three things based on your needs and requirements
aria-hidden="true" - will remove the entire element from the accessibility API
role= "presentation" - The presentation role is used to remove semantic meaning from an element and any of its related child elements.
role= "none" - will remove the semantic meaning of an element while still exposing it to assistive technology.
There are limitations as well:
Hide content from assistive technology
Cannot be used on a focusable
Element cannot be used on the parent of an interactive element
You can actually add the eslint override as a comment in JSX.
You have to nest the comment inside of braces {}, so that it will be interpreted as JavaScript. Then, of course, since it is a JavaScript comment, it will not be rendered in the JSX.
Depending on your style preference, you can either do it on the line directly before the code
{/* eslint-disable-next-line */}
<li key={faqKey} className={styles.entry} onClick={handleExpandFn}>
or, at the end of the same line
<li key={faqKey} className={styles.entry} onClick={handleExpandFn}> {/* eslint-disable-line */}
Check out the docs for more information on using JavaScript inside of JSX.
use
aria-hidden="true"
on non interactive element tag. like
<span aria-hidden="true" onClick={() => void}>Text</span>
Instead of rolling my implementation of faq table with collapse/expand interactive feature, I replace it with react-collapsible.
It of course gets rid of the jsx-a11y/no-static-element-interactions as a result.

Resources