feat: add template-no-noninteractive-element-to-interactive-role#21
feat: add template-no-noninteractive-element-to-interactive-role#21
Conversation
🏎️ Benchmark Comparison
Full mitata output |
There was a problem hiding this comment.
Pull request overview
Adds a new Ember template accessibility rule to flag native non-interactive HTML elements that are assigned interactive ARIA roles, mirroring the intent/coverage of eslint-plugin-jsx-a11y’s no-noninteractive-element-to-interactive-role.
Changes:
- Introduces
template-no-noninteractive-element-to-interactive-rolerule, deriving non-interactive tags fromaria-query+axobject-query, and reusing a shared interactive-role set. - Adds unit tests plus an extensive peer-parity audit fixture against jsx-a11y.
- Adds
axobject-queryas a direct dependency and documents the new rule (docs + README rule list).
Reviewed changes
Copilot reviewed 7 out of 8 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
lib/rules/template-no-noninteractive-element-to-interactive-role.js |
Implements the new rule and non-interactive tag derivation logic. |
lib/utils/interactive-roles.js |
Adds shared derived INTERACTIVE_ROLES helper sourced from aria-query. |
tests/lib/rules/template-no-noninteractive-element-to-interactive-role.js |
Adds CI unit tests for the new rule (gjs + hbs parser variants). |
tests/audit/no-noninteractive-element-to-interactive-role/peer-parity.js |
Adds non-CI audit fixture to track parity/divergences vs jsx-a11y. |
docs/rules/template-no-noninteractive-element-to-interactive-role.md |
Adds rule documentation and examples. |
README.md |
Adds the rule to the auto-generated rules table. |
package.json / pnpm-lock.yaml |
Adds axobject-query dependency and lockfile entries. |
Files not reviewed (1)
- pnpm-lock.yaml: Language not supported
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 7 out of 8 changed files in this pull request and generated 4 comments.
Files not reviewed (1)
- pnpm-lock.yaml: Language not supported
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
6020fa7 to
c2c9577
Compare
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 8 out of 9 changed files in this pull request and generated 1 comment.
Files not reviewed (1)
- pnpm-lock.yaml: Language not supported
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 8 out of 9 changed files in this pull request and generated no new comments.
Files not reviewed (1)
- pnpm-lock.yaml: Language not supported
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 8 out of 9 changed files in this pull request and generated 2 comments.
Files not reviewed (1)
- pnpm-lock.yaml: Language not supported
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
e6fa9ed to
0f1c698
Compare
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 6 out of 6 changed files in this pull request and generated 3 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
2410f78 to
c19253d
Compare
1386766 to
89a6f1d
Compare
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 5 out of 5 changed files in this pull request and generated 1 comment.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| // Exclude `header` — its role depends on ancestry (banner when direct child | ||
| // of body, generic otherwise). Matches jsx-a11y's carve-out. | ||
| tags.delete('header'); |
There was a problem hiding this comment.
The header carve-out is a behaviorally important special case, but the new test suite doesn’t appear to assert it. Add a valid fixture for <header role=\"button\"></header> (in both the <template>...</template> and .hbs RuleTester blocks if applicable) to prevent regressions where header accidentally re-enters NON_INTERACTIVE_TAGS.
…der role=button carve-out test
Note
This is part of a series where Claude has audited
eslint-plugin-emberagainst jsx-a11y, vuejs-accessibility, angular-eslint, lit-a11y and html-validate,ember-template-lint, and the HTML and WCAG specs.<h1>,<article>,<ul>,<table>,<form>,<img>,<p>, etc., all map to non-interactive roles.<h1 role="button">) creates a widget with no backing behavior — focus, keyboard activation, and state handling all have to be added manually, and the mismatch is a recurring source of a11y bugs.Fix: add
template-no-noninteractive-element-to-interactive-role.The non-interactive-tag set is derived by unioning two sources — aria-query's
elementRolesand axobject-query'selementAXObjects— matching jsx-a11y'sisNonInteractiveElement.headeris explicitly excluded because its role is ancestry-dependent, mirroring jsx-a11y's carve-out. Interactive-role set is imported from the sharedlib/utils/interactive-roles.jshelper (see #27).Adds
axobject-queryas a direct dependency.<div>and<span>aren't covered — ARIA 1.2 treats them asgenericwith no inherent semantics to mismatch.Follow-up fix (Phase 3 audit F4)
Commit
4cd92691augments the original axobject-query-only derivation with anelementRolespass. The prior derivation dropped every tag whose axobject-query schema had an attribute constraint, producing false negatives for 18 HTML-AAM-mapped non-interactive tags:<section role="button">,<fieldset role="checkbox">,<hr role="button" />, etc. are now reported, matching jsx-a11y. Audit fixture updated: 23 divergence cases moved to parity-invalid.Flags
Allows
Prior art
no-noninteractive-element-to-interactive-roleelementRoles+ axobject-queryelementAXObjectsunioned set.src/rules/).packages/eslint-plugin-template/src/rules/).lib/rules/).Not added to
template-lint-migration— opt-in.