Skip to content

Extract rule: template-require-aria-activedescendant-tabindex#2599

Merged
NullVoxPopuli merged 2 commits intoember-cli:masterfrom
NullVoxPopuli:nvp/template-lint-extract-rule-template-require-aria-activedescendant-tabindex
Mar 20, 2026
Merged

Extract rule: template-require-aria-activedescendant-tabindex#2599
NullVoxPopuli merged 2 commits intoember-cli:masterfrom
NullVoxPopuli:nvp/template-lint-extract-rule-template-require-aria-activedescendant-tabindex

Conversation

@NullVoxPopuli
Copy link
Contributor

Split from #2371.

Copy link

@NullVoxPopuli-ai-agent NullVoxPopuli-ai-agent left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review: template-require-aria-activedescendant-tabindex (PR #2599)

Comparison with ember-template-lint require-aria-activedescendant-tabindex.js

General correctness:

  1. Interactive element check: The original uses isInteractiveElement(node) from a shared helper which comprehensively checks interactive elements (button, input, select, textarea, a[href], and more based on roles/attributes). The PR uses a simple hardcoded INTERACTIVE_ELEMENTS set with input, button, select, textarea and a manual check for <a> with href. This is a reasonable simplification but may miss some edge cases the original's more comprehensive helper handles (e.g., elements with contenteditable, role="button", etc.). Consider noting this as a known simplification.

  2. HTML tags check: The original uses dom from aria-query to get all valid HTML tags, filtering out custom components. The PR uses isCustomComponent(tag) which checks for PascalCase or dotted paths. This is a good pragmatic approach for Ember/Glimmer where components follow these naming conventions.

  3. Tabindex value logic — potential bug: The original has a bug where it checks tabindexValue === Number.naN — this comparison always returns false since NaN !== NaN in JavaScript. This means in the original, if tabindex cannot be parsed, it falls through to the < 0 check, and since NaN < 0 is false, it doesn't report an error when tabindex is unparseable.

    The PR's getTabindexNumericValue function returns { exists: true, known: false } for unparseable values, and the rule skips reporting for unknown values ("Unknown dynamic values are assumed valid"). This is actually more correct behavior than the original's accidental NaN handling.

  4. Different treatment of text vs mustache tabindex: The PR differentiates: for GlimmerTextNode, it allows -1 and above; for GlimmerMustacheStatement, it only allows non-negative. This asymmetry is intentional but different from the original which doesn't make this distinction. The original treats all tabindex values uniformly with < 0. The PR's approach of rejecting tabindex={{-1}} (mustache) while allowing tabindex="-1" (text) seems inconsistent. A tabindex="-1" element IS keyboard-focusable programmatically which is valid with aria-activedescendant. Consider treating both forms the same way.

  5. Test for tabindex="0" without quotes: <div aria-activedescendant="some-id" tabindex=0> — the 0 without quotes is parsed as GlimmerTextNode with chars "0", which parses to 0, so this correctly passes. Good.

Scope analysis (gjs/gts):

This rule only checks HTML element attributes (aria-activedescendant, tabindex) on GlimmerElementNode. No helper/component name string matching. No scope analysis needed.

Overall: Good migration. The main concern is the asymmetric treatment of tabindex values between text nodes and mustache statements — consider aligning them.

🤖 Automated review comparing with ember-template-lint source

@NullVoxPopuli NullVoxPopuli force-pushed the nvp/template-lint-extract-rule-template-require-aria-activedescendant-tabindex branch from a5f675e to 01fbb79 Compare March 20, 2026 19:23
@NullVoxPopuli NullVoxPopuli merged commit 9223868 into ember-cli:master Mar 20, 2026
9 checks passed
@NullVoxPopuli NullVoxPopuli deleted the nvp/template-lint-extract-rule-template-require-aria-activedescendant-tabindex branch March 20, 2026 21:05
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants