]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-22453 Use the new DropdownMenu from Echoes for the user menu
authorDavid Cho-Lerat <david.cho-lerat@sonarsource.com>
Mon, 15 Jul 2024 15:19:26 +0000 (17:19 +0200)
committersonartech <sonartech@sonarsource.com>
Tue, 16 Jul 2024 20:02:55 +0000 (20:02 +0000)
server/sonar-web/src/main/js/app/components/nav/global/GlobalNavUser.tsx
server/sonar-web/src/main/js/app/components/nav/global/GlobalNavUserMenu.tsx
server/sonar-web/src/main/js/app/components/nav/global/__tests__/GlobalNavUser-test.tsx

index e9d95f3a2bf41c7cbb3d7057fa25840dcc73a9d1..ffee37efd99c61f55e5392c1d0770af0b907b46f 100644 (file)
  * along with this program; if not, write to the Free Software Foundation,
  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
  */
-import {
-  Avatar,
-  BareButton,
-  ButtonSecondary,
-  Dropdown,
-  PopupPlacement,
-  PopupZLevel,
-} from 'design-system';
+import { DropdownMenu, DropdownMenuAlign, Tooltip } from '@sonarsource/echoes-react';
+import { Avatar, BareButton, ButtonSecondary } from 'design-system';
 import * as React from 'react';
-import Tooltip from '../../../../components/controls/Tooltip';
 import { translate } from '../../../../helpers/l10n';
 import { getBaseUrl } from '../../../../helpers/system';
 import { GlobalSettingKeys } from '../../../../types/settings';
@@ -60,31 +53,22 @@ export function GlobalNavUser() {
   const gravatarServerUrl = settings[GlobalSettingKeys.GravatarServerUrl] ?? '';
 
   return (
-    <Dropdown
+    <DropdownMenu.Root
+      align={DropdownMenuAlign.End}
+      header={{ helpText: currentUser.email ?? '', label: currentUser.name }}
       id="userAccountMenuDropdown"
-      placement={PopupPlacement.BottomRight}
-      zLevel={PopupZLevel.Global}
-      overlay={<GlobalNavUserMenu currentUser={currentUser} />}
+      items={<GlobalNavUserMenu />}
     >
-      {({ a11yAttrs: { role, ...a11yAttrs }, onToggleClick, open }) => (
-        <Tooltip
-          mouseEnterDelay={0.2}
-          content={!open ? translate('global_nav.account.tooltip') : undefined}
-        >
-          <BareButton
-            aria-label={translate('global_nav.account.tooltip')}
-            onClick={onToggleClick}
-            {...a11yAttrs}
-          >
-            <Avatar
-              enableGravatar={enableGravatar}
-              gravatarServerUrl={gravatarServerUrl}
-              hash={currentUser.avatar}
-              name={currentUser.name}
-            />
-          </BareButton>
-        </Tooltip>
-      )}
-    </Dropdown>
+      <Tooltip content={translate('global_nav.account.tooltip')}>
+        <BareButton aria-label={translate('global_nav.account.tooltip')}>
+          <Avatar
+            enableGravatar={enableGravatar}
+            gravatarServerUrl={gravatarServerUrl}
+            hash={currentUser.avatar}
+            name={currentUser.name}
+          />
+        </BareButton>
+      </Tooltip>
+    </DropdownMenu.Root>
   );
 }
index 941de1625f66471ae3335bd53ddc1bb1c70d6e13..4542d126bc4d69733f35dbcf2039683cbb1d10d7 100644 (file)
  * along with this program; if not, write to the Free Software Foundation,
  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
  */
-import {
-  ItemButton,
-  ItemDivider,
-  ItemHeader,
-  ItemHeaderHighlight,
-  ItemNavLink,
-} from 'design-system';
+
+import { DropdownMenu } from '@sonarsource/echoes-react';
 import * as React from 'react';
-import { useNavigate } from 'react-router-dom';
 import { translate } from '../../../../helpers/l10n';
-import { LoggedInUser } from '../../../../types/users';
-
-interface UserAccountMenuProps {
-  currentUser: LoggedInUser;
-}
-
-export function GlobalNavUserMenu({ currentUser }: UserAccountMenuProps) {
-  const navigateTo = useNavigate();
-  const firstItemRef = React.useRef<HTMLAnchorElement>(null);
-
-  const handleLogout = React.useCallback(() => {
-    navigateTo('/sessions/logout');
-  }, [navigateTo]);
-
-  React.useEffect(() => {
-    firstItemRef.current?.focus();
-  }, [firstItemRef]);
 
+export function GlobalNavUserMenu() {
   return (
     <>
-      <ItemHeader>
-        <ItemHeaderHighlight title={currentUser.name}>{currentUser.name}</ItemHeaderHighlight>
-        {currentUser.email != null && (
-          <div className="sw-mt-1" title={currentUser.email}>
-            {currentUser.email}
-          </div>
-        )}
-      </ItemHeader>
-      <ItemDivider />
-      <ItemNavLink end to="/account" innerRef={firstItemRef}>
+      <DropdownMenu.ItemLink isMatchingFullPath to="/account">
         {translate('my_account.page')}
-      </ItemNavLink>
-      <ItemDivider />
-      <ItemButton onClick={handleLogout}>{translate('layout.logout')}</ItemButton>
+      </DropdownMenu.ItemLink>
+
+      <DropdownMenu.Separator />
+
+      <DropdownMenu.ItemLink to="/sessions/logout">
+        {translate('layout.logout')}
+      </DropdownMenu.ItemLink>
     </>
   );
 }
index 2598be73adf494c0471b883739713c33a232f3c9..d6d58becb43b4cfe723cd7340a737d481eebbe37 100644 (file)
@@ -17,6 +17,7 @@
  * along with this program; if not, write to the Free Software Foundation,
  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
  */
+
 import { screen } from '@testing-library/react';
 import userEvent from '@testing-library/user-event';
 import * as React from 'react';
@@ -35,12 +36,7 @@ it('should render the right interface for logged in user', async () => {
   renderGlobalNavUser();
   await user.click(screen.getByRole('button'));
 
-  expect(screen.getAllByRole('menuitem')).toHaveLength(3);
-
-  // This line fails with the following issue:
-  // Will lose the focus to the body
-  // Remove the comment tag after fixing the issue
-  // expect(screen.getByRole('menuitem', { name: 'my_account.page' })).toHaveFocus();
+  expect(screen.getAllByRole('menuitem')).toHaveLength(2);
 });
 
 function renderGlobalNavUser(overrides: { currentUser?: CurrentUser } = {}) {