# Non-interactive elements with tabindex='0' must have an interactive ARIA role so assistive technologies can convey their purpose.

> Canonical HTML version: https://rocketvalidator.com/accessibility-validation/accesslint/0.16/keyboard-accessible/focus-order
> Attribution: Rocket Validator (https://rocketvalidator.com)
> License: CC BY 4.0 (https://creativecommons.org/licenses/by/4.0/)

When a non-interactive HTML element like a `<div>` or `<span>` receives `tabindex="0"`, it becomes part of the keyboard tab order. Users can focus it with the Tab key, just like a button or link. But screen readers have no way to determine what the element actually does. They announce it generically, often as just "group" or with the text content alone, giving no indication that it's clickable, toggleable, or otherwise interactive.

This creates a confusing experience for screen reader users. A sighted user might see visual cues (a pointer cursor, a hover effect) that suggest interactivity, but a screen reader user hears no such cues. They land on the element, hear some text, and have no idea they're expected to activate it. Keyboard-only users face a related problem: they can focus the element, but without proper keyboard event handlers, pressing Enter or Space does nothing.

This rule checks that any non-interactive element with `tabindex="0"` also has an interactive ARIA role such as `button`, `link`, `tab`, `menuitem`, or similar. The role tells assistive technologies what kind of interactive control the element is, so they can announce it correctly.

## Why this matters

This issue relates to WCAG Success Criterion 4.1.2: Name, Role, Value (Level A). This criterion requires that all user interface components have a name and role that can be programmatically determined. When a `<div>` with `tabindex="0"` acts as a button but has no `role="button"`, assistive technologies cannot determine its role. The component fails this requirement.

Screen reader users are the most directly affected group. Without a declared role, they cannot distinguish between a focusable element that does something and one that is merely in the tab order by mistake. Keyboard-only users are also affected because elements lacking proper keyboard event handlers won't respond to expected key presses.

## How to fix it

The best fix is to use a native interactive HTML element instead of a `<div>` or `<span>`. A `<button>` element already has the correct role, keyboard behavior, and focus handling built in. A `<a href="...">` element already behaves as a link. Native elements are almost always the right choice.

If a native element truly cannot be used, three things are needed:

1. Add an appropriate ARIA role to the element. Use `role="button"` if it triggers an action, `role="link"` if it navigates, `role="tab"` if it's part of a tabbed interface, and so on.
2. Add keyboard event handlers. Buttons should respond to both Enter and Space. Links should respond to Enter.
3. Make sure the element has an accessible name, either from its text content, an `aria-label`, or `aria-labelledby`.

## Examples

### Incorrect: focusable `<div>` with no role

This `<div>` is in the tab order but has no role. A screen reader might announce it as "Delete" with no indication that it's a button.

```html
<div tabindex="0" onclick="deleteItem()">
  Delete
</div>
```

### Correct: use a native `<button>` element

The simplest fix is to replace the `<div>` with a `<button>`. No `tabindex` or `role` is needed because the element already has the correct semantics and keyboard behavior.

```html
<button type="button" onclick="deleteItem()">
  Delete
</button>
```

### Correct: add a role and keyboard handling to the `<div>`

If a native element cannot be used, add `role="button"` and handle keyboard events. A button should activate on both Enter and Space.

```html
<div
  tabindex="0"
  role="button"
  onclick="deleteItem()"
  onkeydown="if(event.key === 'Enter' || event.key === ' ') { event.preventDefault(); deleteItem(); }">
  Delete
</div>
```

### Incorrect: focusable `<span>` used as a link

This `<span>` navigates to another page but has no `role` or keyboard support.

```html
<span tabindex="0" onclick="location.href='/settings'">
  Settings
</span>
```

### Correct: use a native `<a>` element

```html
<a href="/settings">
  Settings
</a>
```

### Correct: add `role="link"` and keyboard handling

```html
<span
  tabindex="0"
  role="link"
  onclick="location.href='/settings'"
  onkeydown="if(event.key === 'Enter') { location.href='/settings'; }">
  Settings
</span>
```

In every case, using native HTML elements (`<button>`, `<a>`, `<input>`, `<select>`) is preferred over adding ARIA roles to non-interactive elements. Native elements handle focus, keyboard interaction, and role announcements automatically, reducing the chance of errors.
