]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-18902: Improve a11y on Administration/Users page (#8124)
authorvikvorona <viktor.vorona@sonarsource.com>
Tue, 25 Apr 2023 12:59:38 +0000 (14:59 +0200)
committersonartech <sonartech@sonarsource.com>
Tue, 25 Apr 2023 20:03:00 +0000 (20:03 +0000)
server/sonar-web/src/main/js/apps/users/UsersList.tsx
server/sonar-web/src/main/js/apps/users/components/UserGroups.tsx
server/sonar-web/src/main/js/apps/users/components/UserListItem.tsx
server/sonar-web/src/main/js/apps/users/components/UserListItemIdentity.tsx
server/sonar-web/src/main/js/apps/users/components/__tests__/__snapshots__/UserGroups-test.tsx.snap
server/sonar-web/src/main/js/apps/users/components/__tests__/__snapshots__/UserListItem-test.tsx.snap
server/sonar-web/src/main/js/apps/users/components/__tests__/__snapshots__/UserListItemIdentity-test.tsx.snap
sonar-core/src/main/resources/org/sonar/l10n/core.properties

index 2b230b8cabdfa90fdf93f8c08064055d2978a2c0..d1f3349c96050e31be9e06a247aa8c594e61ed1e 100644 (file)
@@ -48,8 +48,7 @@ export default function UsersList({
       <table className="data zebra" id="users-list">
         <thead>
           <tr>
-            <th />
-            <th className="nowrap" />
+            <th className="nowrap">{translate('users.user_name')}</th>
             <th className="nowrap">{translate('my_profile.scm_accounts')}</th>
             <th className="nowrap">{translate('users.last_connection')}</th>
             <th className="nowrap">
@@ -62,7 +61,7 @@ export default function UsersList({
             <th className="nowrap">{translate('my_profile.groups')}</th>
             <th className="nowrap">{translate('users.tokens')}</th>
             {(manageProvider === undefined || users.some((u) => !u.managed)) && (
-              <th className="nowrap">&nbsp;</th>
+              <th className="nowrap">{translate('actions')}</th>
             )}
           </tr>
         </thead>
index f237f01f56b848823ab8cb464985cfaa8180928e..73cfd23aff44df7f506e8c274f3402e2f1bc71a2 100644 (file)
@@ -18,7 +18,7 @@
  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
  */
 import * as React from 'react';
-import { ButtonIcon } from '../../../components/controls/buttons';
+import { ButtonIcon, ButtonLink } from '../../../components/controls/buttons';
 import BulletListIcon from '../../../components/icons/BulletListIcon';
 import { translate, translateWithParameters } from '../../../helpers/l10n';
 import { User } from '../../../types/users';
@@ -44,8 +44,7 @@ export default class UserGroups extends React.PureComponent<Props, State> {
   handleOpenForm = () => this.setState({ openForm: true });
   handleCloseForm = () => this.setState({ openForm: false });
 
-  toggleShowMore = (evt: React.SyntheticEvent<HTMLAnchorElement>) => {
-    evt.preventDefault();
+  toggleShowMore = () => {
     this.setState((state) => ({ showMore: !state.showMore }));
   };
 
@@ -69,9 +68,9 @@ export default class UserGroups extends React.PureComponent<Props, State> {
           ))}
         <li className="little-spacer-bottom">
           {groups.length > GROUPS_LIMIT && !showMore && (
-            <a className="js-user-more-groups spacer-right" href="#" onClick={this.toggleShowMore}>
+            <ButtonLink className="js-user-more-groups spacer-right" onClick={this.toggleShowMore}>
               {translateWithParameters('more_x', groups.length - limit)}
-            </a>
+            </ButtonLink>
           )}
           {manageProvider === undefined && (
             <ButtonIcon
index 601eb637aeae4819daa2ab8194f027089d992f7d..fd0984bce2f99e3ff49bf380b8781e07fbcb38ca 100644 (file)
@@ -54,14 +54,16 @@ export default function UserListItem(props: UserListItemProps) {
 
   return (
     <tr>
-      <td className="thin nowrap text-middle">
-        <Avatar hash={user.avatar} name={user.name} size={36} />
+      <td className="thin text-middle">
+        <div className="sw-flex sw-items-center">
+          <Avatar className="sw-shrink-0 sw-mr-4" hash={user.avatar} name={user.name} size={36} />
+          <UserListItemIdentity
+            identityProvider={identityProvider}
+            user={user}
+            manageProvider={manageProvider}
+          />
+        </div>
       </td>
-      <UserListItemIdentity
-        identityProvider={identityProvider}
-        user={user}
-        manageProvider={manageProvider}
-      />
       <td className="thin text-middle">
         <UserScmAccounts scmAccounts={user.scmAccounts || []} />
       </td>
index 5a467e51f794f23340a3995b694cefe1e87a9184..6438cc6225ad7fc416087f24351f84bf4b9f40b7 100644 (file)
@@ -34,7 +34,7 @@ export interface Props {
 
 export default function UserListItemIdentity({ identityProvider, user, manageProvider }: Props) {
   return (
-    <td className="text-middle">
+    <div>
       <div>
         <strong className="js-user-name">{user.name}</strong>
         <span className="js-user-login note little-spacer-left">{user.login}</span>
@@ -46,7 +46,7 @@ export default function UserListItemIdentity({ identityProvider, user, managePro
       {!user.managed && manageProvider !== undefined && (
         <span className="badge">{translate('local')}</span>
       )}
-    </td>
+    </div>
   );
 }
 
index 27947eee208be8d33f3c5a18fb1a908c84e83d64..44c695ef3de6952dee4b22b1b8dc58c65028523e 100644 (file)
@@ -17,13 +17,12 @@ exports[`should render correctly 1`] = `
   <li
     className="little-spacer-bottom"
   >
-    <a
+    <ButtonLink
       className="js-user-more-groups spacer-right"
-      href="#"
       onClick={[Function]}
     >
       more_x.2
-    </a>
+    </ButtonLink>
     <ButtonIcon
       aria-label="users.update_users_groups.obi"
       className="js-user-groups button-small"
index 536a0a54c2777870e74d720586a4d459048c6114..3b7305310a4e776cd19f439f7c8e5877d7ac2618 100644 (file)
@@ -3,27 +3,32 @@
 exports[`should render correctly 1`] = `
 <tr>
   <td
-    className="thin nowrap text-middle"
+    className="thin text-middle"
   >
-    <withAppStateContext(Avatar)
-      name="One"
-      size={36}
-    />
+    <div
+      className="sw-flex sw-items-center"
+    >
+      <withAppStateContext(Avatar)
+        className="sw-shrink-0 sw-mr-4"
+        name="One"
+        size={36}
+      />
+      <UserListItemIdentity
+        user={
+          {
+            "active": true,
+            "lastConnectionDate": "2019-01-18T15:06:33+0100",
+            "local": false,
+            "login": "obi",
+            "managed": false,
+            "name": "One",
+            "scmAccounts": [],
+            "sonarLintLastConnectionDate": "2019-01-16T15:06:33+0100",
+          }
+        }
+      />
+    </div>
   </td>
-  <UserListItemIdentity
-    user={
-      {
-        "active": true,
-        "lastConnectionDate": "2019-01-18T15:06:33+0100",
-        "local": false,
-        "login": "obi",
-        "managed": false,
-        "name": "One",
-        "scmAccounts": [],
-        "sonarLintLastConnectionDate": "2019-01-16T15:06:33+0100",
-      }
-    }
-  />
   <td
     className="thin text-middle"
   >
@@ -105,27 +110,32 @@ exports[`should render correctly 1`] = `
 exports[`should render correctly without last connection date 1`] = `
 <tr>
   <td
-    className="thin nowrap text-middle"
+    className="thin text-middle"
   >
-    <withAppStateContext(Avatar)
-      name="One"
-      size={36}
-    />
+    <div
+      className="sw-flex sw-items-center"
+    >
+      <withAppStateContext(Avatar)
+        className="sw-shrink-0 sw-mr-4"
+        name="One"
+        size={36}
+      />
+      <UserListItemIdentity
+        user={
+          {
+            "active": true,
+            "lastConnectionDate": "2019-01-18T15:06:33+0100",
+            "local": false,
+            "login": "obi",
+            "managed": false,
+            "name": "One",
+            "scmAccounts": [],
+            "sonarLintLastConnectionDate": "2019-01-16T15:06:33+0100",
+          }
+        }
+      />
+    </div>
   </td>
-  <UserListItemIdentity
-    user={
-      {
-        "active": true,
-        "lastConnectionDate": "2019-01-18T15:06:33+0100",
-        "local": false,
-        "login": "obi",
-        "managed": false,
-        "name": "One",
-        "scmAccounts": [],
-        "sonarLintLastConnectionDate": "2019-01-16T15:06:33+0100",
-      }
-    }
-  />
   <td
     className="thin text-middle"
   >
index 9fd139b23b9e4f4efdd30ac8c38701e2202497ad..48791a5d06502e2c46ea49156c0a91d60a9e1487 100644 (file)
@@ -36,9 +36,7 @@ exports[`#ExternalProvider should render the user external provider and identity
 `;
 
 exports[`#UserListItemIdentity should render correctly 1`] = `
-<td
-  className="text-middle"
->
+<div>
   <div>
     <strong
       className="js-user-name"
@@ -79,5 +77,5 @@ exports[`#UserListItemIdentity should render correctly 1`] = `
       }
     }
   />
-</td>
+</div>
 `;
index 203a43cd8a8d664921d238c071ee2b42384c0019..c98f82229cae18d889c94436e43c4be25d19fb10 100644 (file)
@@ -4407,6 +4407,7 @@ users.update_groups=Update Groups
 users.manage_user=Update {0}
 users.update_tokens=Update tokens
 users.update_tokens_for_x=Update tokens for user {0}
+users.user_name=Name
 users.add=Add user
 users.remove=Remove user
 users.search_description=Search users by login or name