💼 This rule is enabled in the 📋 template-lint-migration config.
Disallows nested interactive elements in templates.
Nested interactive elements (like a button inside a link) are not accessible to keyboard and screen reader users. This creates confusion about which element is actually interactive and can cause unexpected behavior.
This rule disallows nesting interactive elements inside other interactive elements.
Interactive elements include:
<a>(only when it has anhrefattribute)<button><details><embed><iframe><input>(excepttype="hidden")<label><select><summary><textarea>- Elements with interactive ARIA roles (e.g.,
role="button",role="link") - Elements with
tabindex(unlessignoreTabindexis enabled) - Elements with
contenteditable(exceptcontenteditable="false") - Elements with
usemap(<img>,<object>only, unlessignoreUsemapis enabled)
Special cases:
<label>may contain one interactive child (e.g.,<label><input /></label>is fine, but<label><input /><button>x</button></label>is not)<summary>as the first child of<details>is allowed- Nested
role="menuitem"elements are allowed (menu/sub-menu pattern)
Examples of incorrect code for this rule:
<template>
<button>
<a href="#">Link inside button</a>
</button>
</template><template>
<a href="#">
<button>Button inside link</button>
</a>
</template><template>
<label>
<input type="text" />
<button>Submit</button>
</label>
</template>Examples of correct code for this rule:
<template>
<div>
<button>Button</button>
<a href="#">Link</a>
</div>
</template><template>
<label>
<input type="text" />
Label text
</label>
</template><template>
<details>
<summary>Toggle</summary>
Content here
</details>
</template><template>
<a>Not interactive without href</a>
</template>| Name | Type | Default | Description |
|---|---|---|---|
additionalInteractiveTags |
string[] |
[] |
Extra tag names to consider interactive. |
ignoredTags |
string[] |
[] |
Tag names to skip checking. |
ignoreTabindex |
boolean |
false |
If true, tabindex does not make an element interactive. |
ignoreUsemap |
boolean |
false |
If true, usemap does not make an element interactive. |
ignoreUsemapAttribute |
boolean |
false |
Alias for ignoreUsemap (original ember-template-lint name). |