jsx-a11y/no-static-element-interactions

Require a role on <div>, <span> and similar elements that have event handlers

Also called jsx_a11y/no-static-element-interactions

A <div> or a <span> says nothing about what it is. With a click handler, it works like a button for mouse users, but a screen reader only announces its text, so nobody else knows they can press it.

Use the real element, such as <button> or <a href>. If you can't, give the element a role that says what it is. An <a> without an href counts as static too.

Not reported:

  • components
  • elements with aria-hidden
  • elements with role="presentation" or role="none". Use one of these for a handler that only catches events from children.

For elements that describe content, such as <li> or <p>, see jsx-a11y/no-noninteractive-element-interactions.

Configure#

Off by default. To turn it on:

bunfig.toml
[lint.rules]
"jsx-a11y/no-static-element-interactions" = "error" # or "warn"

Every option, set to its default:

bunfig.toml
[lint.rules]
"jsx-a11y/no-static-element-interactions" = ["error", {
  handlers = [
    "onClick",
    "onMouseDown",
    "onMouseUp",
    "onKeyPress",
    "onKeyDown",
    "onKeyUp",
  ],
  allowExpressionValues = false,
}]

Examples#

example.jsx2 problems
const close = <div className="close" onClick={closeDialog}>Close</div>;
const more = <a onClick={loadMore}>Show more</a>;
example.jsxNo problems
const close = <button className="close" onClick={closeDialog}>Close</button>;
const more = <button onClick={loadMore}>Show more</button>;

const custom = (
  <div role="button" tabIndex={0} onClick={closeDialog} onKeyDown={closeOnEnter}>
    Close
  </div>
);

const backdrop = <div role="presentation" onClick={closeDialog} />;

Options#

OptionDefaultWhat it does
handlers["onClick", "onMouseDown", "onMouseUp", "onKeyPress", "onKeyDown", "onKeyUp"]The handlers to report. Your list replaces the default.
allowExpressionValuesfalseAccept a role that's only known at run time, such as role={role}.
example.jsxNo problems
const card = <div onMouseEnter={showPreview} />;
example.jsxwith { "handlers": ["onClick", "onMouseEnter"] }1 problem
const card = <div onMouseEnter={showPreview} />;
example.jsx1 problem
const cell = <div role={cellRole} onClick={selectCell} />;
example.jsxwith { "allowExpressionValues": true }No problems
const cell = <div role={cellRole} onClick={selectCell} />;