From b25ddd6bf482371116d451f530890fcd74bc2881 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Tue, 17 Feb 2026 00:29:53 +0000
Subject: [PATCH 1/2] Initial plan
From e481c3d11b817c082365de292438d4031ca4c9c0 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Tue, 17 Feb 2026 00:38:37 +0000
Subject: [PATCH 2/2] Add template-no-autofocus-attribute rule implementation,
tests, and docs
Co-authored-by: NullVoxPopuli <199018+NullVoxPopuli@users.noreply.github.com>
---
README.md | 6 ++
docs/rules/template-no-autofocus-attribute.md | 48 ++++++++++++++++
lib/rules/template-no-autofocus-attribute.js | 46 +++++++++++++++
package.json | 1 +
.../rules/template-no-autofocus-attribute.js | 57 +++++++++++++++++++
5 files changed, 158 insertions(+)
create mode 100644 docs/rules/template-no-autofocus-attribute.md
create mode 100644 lib/rules/template-no-autofocus-attribute.js
create mode 100644 tests/lib/rules/template-no-autofocus-attribute.js
diff --git a/README.md b/README.md
index 1997fcd7ea..a11681a5a7 100644
--- a/README.md
+++ b/README.md
@@ -174,6 +174,12 @@ rules in templates can be disabled with eslint directives with mustache or html
🔧 Automatically fixable by the [`--fix` CLI option](https://eslint.org/docs/user-guide/command-line-interface#--fix).\
💡 Manually fixable by [editor suggestions](https://eslint.org/docs/latest/use/core-concepts#rule-suggestions).
+### Accessibility
+
+| Name | Description | 💼 | 🔧 | 💡 |
+| :------------------------------------------------------------------------------- | :--------------------------- | :- | :- | :- |
+| [template-no-autofocus-attribute](docs/rules/template-no-autofocus-attribute.md) | disallow autofocus attribute | | 🔧 | |
+
### Best Practices
| Name | Description | 💼 | 🔧 | 💡 |
diff --git a/docs/rules/template-no-autofocus-attribute.md b/docs/rules/template-no-autofocus-attribute.md
new file mode 100644
index 0000000000..00dc7eae4f
--- /dev/null
+++ b/docs/rules/template-no-autofocus-attribute.md
@@ -0,0 +1,48 @@
+# ember/template-no-autofocus-attribute
+
+🔧 This rule is automatically fixable by the [`--fix` CLI option](https://eslint.org/docs/latest/user-guide/command-line-interface#--fix).
+
+
+
+Disallows the use of `autofocus` attribute on elements.
+
+The `autofocus` attribute can cause usability issues for both sighted and non-sighted users by disrupting expected behavior and screen reader announcements.
+
+## Examples
+
+Examples of **incorrect** code for this rule:
+
+```gjs
+
+
+
+```
+
+```gjs
+
+
+
+```
+
+Examples of **correct** code for this rule:
+
+```gjs
+
+
+
+```
+
+```gjs
+
+
+
+```
+
+## When Not To Use It
+
+If you need to autofocus for specific accessibility or UX requirements and have thoroughly tested with assistive technologies, you may disable this rule for those specific cases.
+
+## References
+
+- [ember-template-lint no-autofocus-attribute](https://github.com/ember-template-lint/ember-template-lint/blob/master/docs/rule/no-autofocus-attribute.md)
+- [MDN autofocus attribute](https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/autofocus)
diff --git a/lib/rules/template-no-autofocus-attribute.js b/lib/rules/template-no-autofocus-attribute.js
new file mode 100644
index 0000000000..c3d274a00f
--- /dev/null
+++ b/lib/rules/template-no-autofocus-attribute.js
@@ -0,0 +1,46 @@
+/** @type {import('eslint').Rule.RuleModule} */
+module.exports = {
+ meta: {
+ type: 'suggestion',
+ docs: {
+ description: 'disallow autofocus attribute',
+ category: 'Accessibility',
+ url: 'https://github.com/ember-cli/eslint-plugin-ember/tree/master/docs/rules/template-no-autofocus-attribute.md',
+ },
+ fixable: 'code',
+ schema: [],
+ messages: {
+ noAutofocus:
+ 'Avoid using autofocus attribute. Autofocusing elements can cause usability issues for sighted and non-sighted users.',
+ },
+ },
+
+ create(context) {
+ return {
+ GlimmerElementNode(node) {
+ const autofocusAttr = node.attributes?.find((attr) => attr.name === 'autofocus');
+
+ if (autofocusAttr) {
+ context.report({
+ node: autofocusAttr,
+ messageId: 'noAutofocus',
+ fix(fixer) {
+ // Remove the attribute including preceding whitespace
+ const sourceCode = context.sourceCode;
+ const text = sourceCode.getText();
+ const attrStart = autofocusAttr.range[0];
+ const attrEnd = autofocusAttr.range[1];
+
+ let removeStart = attrStart;
+ while (removeStart > 0 && /\s/.test(text[removeStart - 1])) {
+ removeStart--;
+ }
+
+ return fixer.removeRange([removeStart, attrEnd]);
+ },
+ });
+ }
+ },
+ };
+ },
+};
diff --git a/package.json b/package.json
index 58134e9d03..f625498f7b 100644
--- a/package.json
+++ b/package.json
@@ -60,6 +60,7 @@
},
"dependencies": {
"@ember-data/rfc395-data": "^0.0.4",
+ "@glimmer/env": "^0.1.7",
"css-tree": "^3.0.1",
"ember-eslint-parser": "^0.5.9",
"ember-rfc176-data": "^0.3.18",
diff --git a/tests/lib/rules/template-no-autofocus-attribute.js b/tests/lib/rules/template-no-autofocus-attribute.js
new file mode 100644
index 0000000000..afee5842d2
--- /dev/null
+++ b/tests/lib/rules/template-no-autofocus-attribute.js
@@ -0,0 +1,57 @@
+//------------------------------------------------------------------------------
+// Requirements
+//------------------------------------------------------------------------------
+
+const rule = require('../../../lib/rules/template-no-autofocus-attribute');
+const RuleTester = require('eslint').RuleTester;
+
+//------------------------------------------------------------------------------
+// Tests
+//------------------------------------------------------------------------------
+
+const ruleTester = new RuleTester({
+ parser: require.resolve('ember-eslint-parser'),
+ parserOptions: { ecmaVersion: 2022, sourceType: 'module' },
+});
+
+ruleTester.run('template-no-autofocus-attribute', rule, {
+ valid: [
+ `
+
+ `,
+ `
+
+ `,
+ ],
+
+ invalid: [
+ {
+ code: `
+
+ `,
+ output: `
+
+ `,
+ errors: [
+ {
+ message:
+ 'Avoid using autofocus attribute. Autofocusing elements can cause usability issues for sighted and non-sighted users.',
+ type: 'GlimmerAttrNode',
+ },
+ ],
+ },
+ {
+ code: `
+
+ `,
+ output: `
+
+ `,
+ errors: [
+ {
+ type: 'GlimmerAttrNode',
+ },
+ ],
+ },
+ ],
+});