# jsx-a11y/no-redundant-roles

> Disallow a `role` that the element already has

Most HTML elements come with a role: a `<button>` is a `button`, a `<ul>` is a `list`. Writing that role again changes nothing, and it's one more thing to update when the element changes.

For `<input>`, `<select>` and `<img>`, the role depends on the other attributes: `<input type="checkbox">` is a `checkbox`, `<input type="range">` is a `slider`. Only a `role` written as a string is checked.

`--fix` removes the `role` attribute.

{/* Generated by src/codegen/lint-rule-docs.ts. Do not edit this section. */}

## Configure

Off by default. To turn it on:

```toml bunfig.toml
[lint.rules]
"jsx-a11y/no-redundant-roles" = "error" # or "warn"
```

{/* End of the generated section. */}

## Examples

Reported:

{/* bad {"count": 3} */}
```jsx
const save = <button role="button">Save</button>;
const items = <ul role="list" />;
const volume = <input type="range" role="slider" />;
```

Not reported:

{/* good */}
```jsx
const save = <button>Save</button>;
const items = <ul />;
const toggle = <button role="switch" aria-checked={enabled} />;
```

## Options

The option is an object that maps an element to the roles you can repeat on it. By default only `<nav role="navigation">` is allowed.

{/* good */}
```jsx
const menu = <nav role="navigation" />;
```

Safari with VoiceOver stops announcing a list once CSS removes its bullets, and `role="list"` brings that back. To allow it:

{/* good {"options": [{"ul": ["list"], "ol": ["list"]}]} */}
```jsx
const items = <ul role="list" className="plain" />;
const menu = <nav role="navigation" />;
```

To report `<nav role="navigation">` as well, give `nav` an empty list:

{/* bad {"options": [{"nav": []}]} */}
```jsx
const menu = <nav role="navigation" />;
```
