]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-18145 Visual heading text is not marked up as heading
authorstanislavh <stanislav.honcharov@sonarsource.com>
Thu, 12 Jan 2023 12:29:38 +0000 (13:29 +0100)
committersonartech <sonartech@sonarsource.com>
Fri, 13 Jan 2023 20:02:47 +0000 (20:02 +0000)
server/sonar-web/src/main/js/app/components/search/SearchResults.tsx
server/sonar-web/src/main/js/app/components/search/__tests__/__snapshots__/SearchResults-test.tsx.snap
server/sonar-web/src/main/js/app/styles/components/menu.css
server/sonar-web/src/main/js/apps/coding-rules/components/SimilarRulesFilter.tsx
server/sonar-web/src/main/js/apps/coding-rules/components/__tests__/__snapshots__/SimilarRulesFilter-test.tsx.snap
server/sonar-web/src/main/js/components/embed-docs-modal/EmbedDocsPopup.tsx

index b6183d3abe0ab6477b10add6d1fafac78514c9dc..df1e70e1ac310e81da0456b8340c3476e5d91d92 100644 (file)
@@ -45,23 +45,29 @@ export default function SearchResults(props: Props): React.ReactElement<Props> {
       const more = props.more[qualifier];
 
       renderedComponents.push(
-        <ul className="menu" key={`header-${qualifier}`}>
-          <li className="menu-header" role="presentation">
+        <>
+          <h2 className="menu-header no-margin" id={translate('qualifiers', qualifier)}>
             {translate('qualifiers', qualifier)}
-          </li>
-          {components.map((component) => props.renderResult(component))}
-          {more !== undefined && more > 0 && (
-            <SearchShowMore
-              allowMore={props.allowMore}
-              key={`more-${qualifier}`}
-              loadingMore={props.loadingMore}
-              onMoreClick={props.onMoreClick}
-              onSelect={props.onSelect}
-              qualifier={qualifier}
-              selected={props.selected === `qualifier###${qualifier}`}
-            />
-          )}
-        </ul>
+          </h2>
+          <ul
+            className="menu"
+            key={`header-${qualifier}`}
+            aria-labelledby={translate('qualifiers', qualifier)}
+          >
+            {components.map((component) => props.renderResult(component))}
+            {more !== undefined && more > 0 && (
+              <SearchShowMore
+                allowMore={props.allowMore}
+                key={`more-${qualifier}`}
+                loadingMore={props.loadingMore}
+                onMoreClick={props.onMoreClick}
+                onSelect={props.onSelect}
+                qualifier={qualifier}
+                selected={props.selected === `qualifier###${qualifier}`}
+              />
+            )}
+          </ul>
+        </>
       );
     }
   });
index 136288b0952ebe0c1da989e3f6f2f27715f69128..c77831d661fcad688bee941e8a4cf53424071d0e 100644 (file)
@@ -2,16 +2,17 @@
 
 exports[`renders "Show More" link 1`] = `
 <div>
+  <h2
+    className="menu-header no-margin"
+    id="qualifiers.TRK"
+  >
+    qualifiers.TRK
+  </h2>
   <ul
+    aria-labelledby="qualifiers.TRK"
     className="menu"
     key="header-TRK"
   >
-    <li
-      className="menu-header"
-      role="presentation"
-    >
-      qualifiers.TRK
-    </li>
     <span
       key="foo"
     >
@@ -36,32 +37,34 @@ exports[`renders "Show More" link 1`] = `
 
 exports[`renders different components and dividers between them 1`] = `
 <div>
+  <h2
+    className="menu-header no-margin"
+    id="qualifiers.FIL"
+  >
+    qualifiers.FIL
+  </h2>
   <ul
+    aria-labelledby="qualifiers.FIL"
     className="menu"
     key="header-FIL"
   >
-    <li
-      className="menu-header"
-      role="presentation"
-    >
-      qualifiers.FIL
-    </li>
     <span
       key="zux"
     >
       zux
     </span>
   </ul>
+  <h2
+    className="menu-header no-margin"
+    id="qualifiers.TRK"
+  >
+    qualifiers.TRK
+  </h2>
   <ul
+    aria-labelledby="qualifiers.TRK"
     className="menu"
     key="header-TRK"
   >
-    <li
-      className="menu-header"
-      role="presentation"
-    >
-      qualifiers.TRK
-    </li>
     <span
       key="foo"
     >
index ce9440bf416b3c1c6f2181c64c55c9f3b0380c95..74286cf1c1c0f81ae59f3d0236be9af215874699 100644 (file)
@@ -31,7 +31,8 @@
   padding-bottom: 12px;
 }
 
-.menu + .menu {
+.menu + .menu,
+.menu + .menu-header {
   border-top: 1px solid var(--barBorderColor);
 }
 
 
 .menu-header {
   padding: var(--gridSize);
+  margin: -8px;
   font-size: 12px;
   color: var(--neutral600);
   white-space: nowrap;
+  line-height: unset;
+}
+
+.menu-header + ul {
+  padding-top: 8px;
+}
+
+.menu-header.no-margin + ul {
+  padding-top: 0;
+}
+
+.menu-header.no-margin {
+  margin: 0;
 }
 
-.menu-header:first-child,
 .divider + .menu-header {
   padding-top: calc(var(--gridSize) - 5px);
 }
index 9396783fc365539ebdf9d93fcebe8450cc6bc0ea..0c3f8e462eab5e38cbc199595d8d9e013d7446e1 100644 (file)
@@ -74,57 +74,61 @@ export default class SimilarRulesFilter extends React.PureComponent<Props> {
       <Dropdown
         className="display-inline-block"
         overlay={
-          <ul className="menu">
-            <li className="menu-header">{translate('coding_rules.filter_similar_rules')}</li>
-            <li>
-              <a
-                data-test="coding-rules__similar-language"
-                href="#"
-                onClick={this.handleLanguageClick}
-              >
-                {rule.langName}
-              </a>
-            </li>
-
-            <li>
-              <a
-                className="display-flex-center"
-                data-test="coding-rules__similar-type"
-                href="#"
-                onClick={this.handleTypeClick}
-              >
-                <IssueTypeIcon query={rule.type} />
-                <span className="little-spacer-left">{translate('issue.type', rule.type)}</span>
-              </a>
-            </li>
-
-            {severity && (
+          <>
+            <h2 className="menu-header" id="filter-similar-rules">
+              {translate('coding_rules.filter_similar_rules')}
+            </h2>
+            <ul className="menu" aria-labelledby="filter-similar-rules">
               <li>
                 <a
-                  data-test="coding-rules__similar-severity"
+                  data-test="coding-rules__similar-language"
                   href="#"
-                  onClick={this.handleSeverityClick}
+                  onClick={this.handleLanguageClick}
                 >
-                  <SeverityHelper className="display-flex-center" severity={rule.severity} />
+                  {rule.langName}
                 </a>
               </li>
-            )}
 
-            {allTags.length > 0 && <li className="divider" />}
-            {allTags.map((tag) => (
-              <li key={tag}>
+              <li>
                 <a
-                  data-tag={tag}
-                  data-test="coding-rules__similar-tag"
+                  className="display-flex-center"
+                  data-test="coding-rules__similar-type"
                   href="#"
-                  onClick={this.handleTagClick}
+                  onClick={this.handleTypeClick}
                 >
-                  <TagsIcon className="little-spacer-right text-middle" />
-                  <span className="text-middle">{tag}</span>
+                  <IssueTypeIcon query={rule.type} />
+                  <span className="little-spacer-left">{translate('issue.type', rule.type)}</span>
                 </a>
               </li>
-            ))}
-          </ul>
+
+              {severity && (
+                <li>
+                  <a
+                    data-test="coding-rules__similar-severity"
+                    href="#"
+                    onClick={this.handleSeverityClick}
+                  >
+                    <SeverityHelper className="display-flex-center" severity={rule.severity} />
+                  </a>
+                </li>
+              )}
+
+              {allTags.length > 0 && <li className="divider" />}
+              {allTags.map((tag) => (
+                <li key={tag}>
+                  <a
+                    data-tag={tag}
+                    data-test="coding-rules__similar-tag"
+                    href="#"
+                    onClick={this.handleTagClick}
+                  >
+                    <TagsIcon className="little-spacer-right text-middle" />
+                    <span className="text-middle">{tag}</span>
+                  </a>
+                </li>
+              ))}
+            </ul>
+          </>
         }
       >
         <a
index 1f890e2fff56a8a66e1d83bd6a8b313e49ea86bd..2585ebc6e1db55117953cba21a1d481089988f80 100644 (file)
@@ -4,107 +4,111 @@ exports[`should render correctly 1`] = `
 <Dropdown
   className="display-inline-block"
   overlay={
-    <ul
-      className="menu"
-    >
-      <li
+    <React.Fragment>
+      <h2
         className="menu-header"
+        id="filter-similar-rules"
       >
         coding_rules.filter_similar_rules
-      </li>
-      <li>
-        <a
-          data-test="coding-rules__similar-language"
-          href="#"
-          onClick={[Function]}
-        >
-          JavaScript
-        </a>
-      </li>
-      <li>
-        <a
-          className="display-flex-center"
-          data-test="coding-rules__similar-type"
-          href="#"
-          onClick={[Function]}
-        >
-          <IssueTypeIcon
-            query="CODE_SMELL"
-          />
-          <span
-            className="little-spacer-left"
+      </h2>
+      <ul
+        aria-labelledby="filter-similar-rules"
+        className="menu"
+      >
+        <li>
+          <a
+            data-test="coding-rules__similar-language"
+            href="#"
+            onClick={[Function]}
           >
-            issue.type.CODE_SMELL
-          </span>
-        </a>
-      </li>
-      <li>
-        <a
-          data-test="coding-rules__similar-severity"
-          href="#"
-          onClick={[Function]}
-        >
-          <SeverityHelper
+            JavaScript
+          </a>
+        </li>
+        <li>
+          <a
             className="display-flex-center"
-            severity="MAJOR"
-          />
-        </a>
-      </li>
-      <li
-        className="divider"
-      />
-      <li>
-        <a
-          data-tag="x"
-          data-test="coding-rules__similar-tag"
-          href="#"
-          onClick={[Function]}
-        >
-          <TagsIcon
-            className="little-spacer-right text-middle"
-          />
-          <span
-            className="text-middle"
+            data-test="coding-rules__similar-type"
+            href="#"
+            onClick={[Function]}
+          >
+            <IssueTypeIcon
+              query="CODE_SMELL"
+            />
+            <span
+              className="little-spacer-left"
+            >
+              issue.type.CODE_SMELL
+            </span>
+          </a>
+        </li>
+        <li>
+          <a
+            data-test="coding-rules__similar-severity"
+            href="#"
+            onClick={[Function]}
+          >
+            <SeverityHelper
+              className="display-flex-center"
+              severity="MAJOR"
+            />
+          </a>
+        </li>
+        <li
+          className="divider"
+        />
+        <li>
+          <a
+            data-tag="x"
+            data-test="coding-rules__similar-tag"
+            href="#"
+            onClick={[Function]}
           >
-            x
-          </span>
-        </a>
-      </li>
-      <li>
-        <a
-          data-tag="a"
-          data-test="coding-rules__similar-tag"
-          href="#"
-          onClick={[Function]}
-        >
-          <TagsIcon
-            className="little-spacer-right text-middle"
-          />
-          <span
-            className="text-middle"
+            <TagsIcon
+              className="little-spacer-right text-middle"
+            />
+            <span
+              className="text-middle"
+            >
+              x
+            </span>
+          </a>
+        </li>
+        <li>
+          <a
+            data-tag="a"
+            data-test="coding-rules__similar-tag"
+            href="#"
+            onClick={[Function]}
           >
-            a
-          </span>
-        </a>
-      </li>
-      <li>
-        <a
-          data-tag="b"
-          data-test="coding-rules__similar-tag"
-          href="#"
-          onClick={[Function]}
-        >
-          <TagsIcon
-            className="little-spacer-right text-middle"
-          />
-          <span
-            className="text-middle"
+            <TagsIcon
+              className="little-spacer-right text-middle"
+            />
+            <span
+              className="text-middle"
+            >
+              a
+            </span>
+          </a>
+        </li>
+        <li>
+          <a
+            data-tag="b"
+            data-test="coding-rules__similar-tag"
+            href="#"
+            onClick={[Function]}
           >
-            b
-          </span>
-        </a>
-      </li>
-    </ul>
+            <TagsIcon
+              className="little-spacer-right text-middle"
+            />
+            <span
+              className="text-middle"
+            >
+              b
+            </span>
+          </a>
+        </li>
+      </ul>
+    </React.Fragment>
   }
 >
   <a
index 498e814f8f1a79901a35b7e7dc3863066a405173..f956e57f92a06da7c88eed9f784ae1e4fd400bea 100644 (file)
@@ -46,11 +46,11 @@ export default class EmbedDocsPopup extends React.PureComponent<Props> {
     }
   };
 
-  renderTitle(text: string) {
+  renderTitle(text: string, labelId: string) {
     return (
-      <li role="presentation" className="menu-header">
+      <h2 className="menu-header" id={labelId}>
         {text}
-      </li>
+      </h2>
     );
   }
 
@@ -59,20 +59,22 @@ export default class EmbedDocsPopup extends React.PureComponent<Props> {
       return null;
     }
     return (
-      <ul className="menu abs-width-240">
-        {this.renderTitle(translate('docs.suggestion'))}
-        {suggestions.map((suggestion, i) => (
-          <li key={suggestion.link}>
-            <DocLink
-              innerRef={i === 0 ? this.focusFirstItem : undefined}
-              onClick={this.props.onClose}
-              to={suggestion.link}
-            >
-              {suggestion.text}
-            </DocLink>
-          </li>
-        ))}
-      </ul>
+      <>
+        {this.renderTitle(translate('docs.suggestion'), 'suggestion')}
+        <ul className="menu abs-width-240" aria-labelledby="suggestion">
+          {suggestions.map((suggestion, i) => (
+            <li key={suggestion.link}>
+              <DocLink
+                innerRef={i === 0 ? this.focusFirstItem : undefined}
+                onClick={this.props.onClose}
+                to={suggestion.link}
+              >
+                {suggestion.text}
+              </DocLink>
+            </li>
+          ))}
+        </ul>
+      </>
     );
   };
 
@@ -118,8 +120,8 @@ export default class EmbedDocsPopup extends React.PureComponent<Props> {
             </Link>
           </li>
         </ul>
-        <ul className="menu abs-width-240">
-          {this.renderTitle(translate('docs.stay_connected'))}
+        {this.renderTitle(translate('docs.stay_connected'), 'stay_connected')}
+        <ul className="menu abs-width-240" aria-labelledby="stay_connected">
           <li>
             {this.renderIconLink(
               'https://www.sonarqube.org/whats-new/?referrer=sonarqube',