From 6ed2b5baf629a6a27b436d4aa0c3e56c78249d45 Mon Sep 17 00:00:00 2001 From: yassin-kammoun-sonarsource Date: Wed, 8 Nov 2023 16:26:30 +0100 Subject: [PATCH] Create rule S6841 (`jsx-a11y/tabindex-no-positive`): `tabIndex` values should be non-positive --- .../jsts/console/typescript-S6841.json | 19 ++++++++ .../sonar/javascript/checks/CheckList.java | 1 + .../checks/TabindexNoPositiveCheck.java | 36 ++++++++++++++++ .../javascript/rules/javascript/S6841.html | 43 +++++++++++++++++++ .../javascript/rules/javascript/S6841.json | 28 ++++++++++++ .../rules/javascript/Sonar_way_profile.json | 3 +- 6 files changed, 129 insertions(+), 1 deletion(-) create mode 100644 its/ruling/src/test/expected/jsts/console/typescript-S6841.json create mode 100644 sonar-plugin/javascript-checks/src/main/java/org/sonar/javascript/checks/TabindexNoPositiveCheck.java create mode 100644 sonar-plugin/javascript-checks/src/main/resources/org/sonar/l10n/javascript/rules/javascript/S6841.html create mode 100644 sonar-plugin/javascript-checks/src/main/resources/org/sonar/l10n/javascript/rules/javascript/S6841.json diff --git a/its/ruling/src/test/expected/jsts/console/typescript-S6841.json b/its/ruling/src/test/expected/jsts/console/typescript-S6841.json new file mode 100644 index 00000000000..0010e23d485 --- /dev/null +++ b/its/ruling/src/test/expected/jsts/console/typescript-S6841.json @@ -0,0 +1,19 @@ +{ +"console:src/views/RelationsPopup/ConfirmPopup.tsx": [ +123 +], +"console:src/views/Settings/Billing/CreditCardBack.tsx": [ +53 +], +"console:src/views/Settings/Billing/CreditCardFront.tsx": [ +209, +220, +231 +], +"console:src/views/models/DatabrowserView/DatabrowserView.tsx": [ +314 +], +"console:src/views/models/FieldPopup/ConfirmFieldPopup.tsx": [ +214 +] +} diff --git a/sonar-plugin/javascript-checks/src/main/java/org/sonar/javascript/checks/CheckList.java b/sonar-plugin/javascript-checks/src/main/java/org/sonar/javascript/checks/CheckList.java index 4422e7ee10e..6d99f7ac6d5 100644 --- a/sonar-plugin/javascript-checks/src/main/java/org/sonar/javascript/checks/CheckList.java +++ b/sonar-plugin/javascript-checks/src/main/java/org/sonar/javascript/checks/CheckList.java @@ -413,6 +413,7 @@ public static List> getAllChecks() { SwitchWithNotEnoughCaseCheck.class, SwitchWithoutDefaultCheck.class, TabCharacterCheck.class, + TabindexNoPositiveCheck.class, TemplateStringMisuseCheck.class, TestCheckExceptionCheck.class, ThrowLiteralCheck.class, diff --git a/sonar-plugin/javascript-checks/src/main/java/org/sonar/javascript/checks/TabindexNoPositiveCheck.java b/sonar-plugin/javascript-checks/src/main/java/org/sonar/javascript/checks/TabindexNoPositiveCheck.java new file mode 100644 index 00000000000..a6aeeac1d01 --- /dev/null +++ b/sonar-plugin/javascript-checks/src/main/java/org/sonar/javascript/checks/TabindexNoPositiveCheck.java @@ -0,0 +1,36 @@ +/** + * SonarQube JavaScript Plugin + * Copyright (C) 2011-2023 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.javascript.checks; + +import org.sonar.check.Rule; +import org.sonar.plugins.javascript.api.EslintBasedCheck; +import org.sonar.plugins.javascript.api.JavaScriptRule; +import org.sonar.plugins.javascript.api.TypeScriptRule; + +@JavaScriptRule +@TypeScriptRule +@Rule(key = "S6841") +public class TabindexNoPositiveCheck implements EslintBasedCheck { + + @Override + public String eslintKey() { + return "tabindex-no-positive"; + } +} diff --git a/sonar-plugin/javascript-checks/src/main/resources/org/sonar/l10n/javascript/rules/javascript/S6841.html b/sonar-plugin/javascript-checks/src/main/resources/org/sonar/l10n/javascript/rules/javascript/S6841.html new file mode 100644 index 00000000000..a05d4a6558b --- /dev/null +++ b/sonar-plugin/javascript-checks/src/main/resources/org/sonar/l10n/javascript/rules/javascript/S6841.html @@ -0,0 +1,43 @@ +

Why is this an issue?

+

Positive tabIndex values can disrupt the natural tab order of the webpage. This can be confusing for screen reader users who rely on a +logical tab order to navigate through the content. If the tab order doesn’t match the visual or logical order of elements, users may struggle to +understand the page structure.

+

Therefore, it’s recommended to avoid using positive tabIndex values.

+

How to fix it

+

If you need to make an element focusable that isn’t by default (like a <div> or <span>), you can use tabIndex="0". This +will add the element to the natural tab order based on its position in the HTML. Otherwise, either remove the tabIndex value or use a +negative value to remove the element from the tab order.

+

Code examples

+

Noncompliant code example

+
+function MyDiv() {
+    return (
+        <div>
+            <span tabIndex="5">foo</span> // Noncompliant
+            <span tabIndex="3">bar</span> // Noncompliant
+            <span tabIndex="1">baz</span> // Noncompliant
+            <span tabIndex="2">qux</span> // Noncompliant
+        </div>
+    );
+}
+
+

Compliant solution

+
+function MyDiv() {
+    return (
+        <div>
+            <span tabIndex="0">foo</span>
+            <span tabIndex="-1">bar</span>
+            <span tabIndex={0}>baz</span>
+            <span>qux</span>
+        </div>
+    );
+}
+
+

Resources

+

Documentation

+ + diff --git a/sonar-plugin/javascript-checks/src/main/resources/org/sonar/l10n/javascript/rules/javascript/S6841.json b/sonar-plugin/javascript-checks/src/main/resources/org/sonar/l10n/javascript/rules/javascript/S6841.json new file mode 100644 index 00000000000..5721c50bf97 --- /dev/null +++ b/sonar-plugin/javascript-checks/src/main/resources/org/sonar/l10n/javascript/rules/javascript/S6841.json @@ -0,0 +1,28 @@ +{ + "title": "\"tabIndex\" values should be non-positive", + "type": "CODE_SMELL", + "status": "ready", + "remediation": { + "func": "Constant\/Issue", + "constantCost": "5min" + }, + "tags": [ + "accessibility" + ], + "defaultSeverity": "Major", + "ruleSpecification": "RSPEC-6841", + "sqKey": "S6841", + "scope": "All", + "quickfix": "infeasible", + "code": { + "impacts": { + "MAINTAINABILITY": "LOW", + "RELIABILITY": "MEDIUM" + }, + "attribute": "CONVENTIONAL" + }, + "compatibleLanguages": [ + "JAVASCRIPT", + "TYPESCRIPT" + ] +} diff --git a/sonar-plugin/javascript-checks/src/main/resources/org/sonar/l10n/javascript/rules/javascript/Sonar_way_profile.json b/sonar-plugin/javascript-checks/src/main/resources/org/sonar/l10n/javascript/rules/javascript/Sonar_way_profile.json index 3602246c652..259df844f08 100644 --- a/sonar-plugin/javascript-checks/src/main/resources/org/sonar/l10n/javascript/rules/javascript/Sonar_way_profile.json +++ b/sonar-plugin/javascript-checks/src/main/resources/org/sonar/l10n/javascript/rules/javascript/Sonar_way_profile.json @@ -306,6 +306,7 @@ "S6824", "S6825", "S6827", - "S6836" + "S6836", + "S6841" ] }