This is an automated email from the ASF dual-hosted git repository.

diegopucci pushed a commit to branch geido/fix/console-cleanup
in repository https://gitbox.apache.org/repos/asf/superset.git

commit cb8524278ed0fb17a9c09381cefb4089250caaa9
Author: Diego Pucci <diegopucci...@gmail.com>
AuthorDate: Mon Aug 4 16:11:55 2025 +0300

    chore(LanguagePicker): Remove deprecated Menu.Item
---
 .../src/features/home/LanguagePicker.stories.tsx   | 26 ++++++--
 .../src/features/home/LanguagePicker.test.tsx      | 37 ++++++-----
 .../src/features/home/LanguagePicker.tsx           | 76 ++++++++++------------
 superset-frontend/src/features/home/RightMenu.tsx  | 18 +++--
 4 files changed, 83 insertions(+), 74 deletions(-)

diff --git a/superset-frontend/src/features/home/LanguagePicker.stories.tsx 
b/superset-frontend/src/features/home/LanguagePicker.stories.tsx
index aa131821ee..3727bd5258 100644
--- a/superset-frontend/src/features/home/LanguagePicker.stories.tsx
+++ b/superset-frontend/src/features/home/LanguagePicker.stories.tsx
@@ -16,8 +16,24 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-import { MainNav as Menu } from '@superset-ui/core/components/Menu'; // Ensure 
correct import path
-import LanguagePicker from './LanguagePicker'; // Ensure correct import path
+import { Menu } from '@superset-ui/core/components/Menu';
+import { useLanguageMenuItems } from './LanguagePicker';
+import type { Languages } from './LanguagePicker';
+
+// Component to demonstrate the hook usage
+const LanguagePicker = ({
+  locale,
+  languages,
+}: {
+  locale: string;
+  languages: Languages;
+}) => {
+  const languageMenuItem = useLanguageMenuItems({ locale, languages });
+
+  return (
+    <Menu aria-label="Languages" items={[languageMenuItem]} mode="horizontal" 
/>
+  );
+};
 
 export default {
   title: 'Components/LanguagePicker',
@@ -48,11 +64,7 @@ const mockedProps = {
   },
 };
 
-const Template = (args: any) => (
-  <Menu disabledOverflow>
-    <LanguagePicker {...args} />
-  </Menu>
-);
+const Template = (args: any) => <LanguagePicker {...args} />;
 
 export const Default = Template.bind({});
 Default.args = mockedProps;
diff --git a/superset-frontend/src/features/home/LanguagePicker.test.tsx 
b/superset-frontend/src/features/home/LanguagePicker.test.tsx
index 59dbeab0ac..bc9ac9cb2d 100644
--- a/superset-frontend/src/features/home/LanguagePicker.test.tsx
+++ b/superset-frontend/src/features/home/LanguagePicker.test.tsx
@@ -17,8 +17,8 @@
  * under the License.
  */
 import { render, screen, userEvent } from 'spec/helpers/testing-library';
-import { MainNav as Menu } from '@superset-ui/core/components/Menu';
-import LanguagePicker from './LanguagePicker';
+import { Menu } from '@superset-ui/core/components/Menu';
+import { useLanguageMenuItems } from './LanguagePicker';
 
 const mockedProps = {
   locale: 'en',
@@ -36,31 +36,34 @@ const mockedProps = {
   },
 };
 
-test('should render', async () => {
-  const { container } = render(
-    <Menu>
-      <LanguagePicker {...mockedProps} />
-    </Menu>,
+// Test component to use the hook
+const TestLanguagePicker = ({ locale, languages }: typeof mockedProps) => {
+  const languageMenuItem = useLanguageMenuItems({ locale, languages });
+
+  return (
+    <Menu aria-label="Languages" items={[languageMenuItem]} mode="horizontal" 
/>
   );
+};
+
+test('should render', async () => {
+  const { container } = render(<TestLanguagePicker {...mockedProps} />, {
+    useRouter: true,
+  });
   expect(await screen.findByRole('menu')).toBeInTheDocument();
   expect(container).toBeInTheDocument();
 });
 
 test('should render the language picker', async () => {
-  render(
-    <Menu>
-      <LanguagePicker {...mockedProps} />
-    </Menu>,
-  );
+  render(<TestLanguagePicker {...mockedProps} />, {
+    useRouter: true,
+  });
   expect(await screen.findByLabelText('Languages')).toBeInTheDocument();
 });
 
 test('should render the items', async () => {
-  render(
-    <Menu>
-      <LanguagePicker {...mockedProps} />
-    </Menu>,
-  );
+  render(<TestLanguagePicker {...mockedProps} />, {
+    useRouter: true,
+  });
   userEvent.hover(screen.getByRole('menuitem'));
   expect(await screen.findByText('English')).toBeInTheDocument();
   expect(await screen.findByText('Italian')).toBeInTheDocument();
diff --git a/superset-frontend/src/features/home/LanguagePicker.tsx 
b/superset-frontend/src/features/home/LanguagePicker.tsx
index 0dddff17d0..f8b5cc9f24 100644
--- a/superset-frontend/src/features/home/LanguagePicker.tsx
+++ b/superset-frontend/src/features/home/LanguagePicker.tsx
@@ -16,12 +16,12 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-import { MainNav as Menu } from '@superset-ui/core/components/Menu';
-import { styled, css, useTheme } from '@superset-ui/core';
+import { useMemo } from 'react';
+import { MenuItem } from '@superset-ui/core/components/Menu';
+import { styled } from '@superset-ui/core';
 import { Icons } from '@superset-ui/core/components/Icons';
 import { Typography } from '@superset-ui/core/components/Typography';
 
-const { SubMenu } = Menu;
 export interface Languages {
   [key: string]: {
     flag: string;
@@ -51,44 +51,34 @@ const StyledLabel = styled.div`
   }
 `;
 
-const StyledFlag = styled.i`
-  margin-top: 2px;
-`;
+export const useLanguageMenuItems = ({
+  locale,
+  languages,
+}: LanguagePickerProps): MenuItem =>
+  useMemo(() => {
+    const items: MenuItem[] = Object.keys(languages).map(langKey => ({
+      key: langKey,
+      label: (
+        <StyledLabel className="f16">
+          <i className={`flag ${languages[langKey].flag}`} />
+          <Typography.Link href={languages[langKey].url}>
+            {languages[langKey].name}
+          </Typography.Link>
+        </StyledLabel>
+      ),
+      style: { whiteSpace: 'normal', height: 'auto' },
+    }));
 
-export default function LanguagePicker(props: LanguagePickerProps) {
-  const { locale, languages, ...rest } = props;
-  const theme = useTheme();
-  return (
-    <SubMenu
-      css={css`
-        [data-icon='caret-down'] {
-          color: ${theme.colors.grayscale.base};
-          font-size: ${theme.fontSizeXS}px;
-          margin-left: ${theme.sizeUnit}px;
-        }
-      `}
-      aria-label="Languages"
-      title={
-        <div className="f16">
-          <StyledFlag className={`flag ${languages[locale].flag}`} />
-        </div>
-      }
-      icon={<Icons.CaretDownOutlined iconSize="xs" />}
-      {...rest}
-    >
-      {Object.keys(languages).map(langKey => (
-        <Menu.Item
-          key={langKey}
-          style={{ whiteSpace: 'normal', height: 'auto' }}
-        >
-          <StyledLabel className="f16">
-            <i className={`flag ${languages[langKey].flag}`} />
-            <Typography.Link href={languages[langKey].url}>
-              {languages[langKey].name}
-            </Typography.Link>
-          </StyledLabel>
-        </Menu.Item>
-      ))}
-    </SubMenu>
-  );
-}
+    return {
+      key: 'language-submenu',
+      type: 'submenu' as const,
+      label: (
+        <span className="f16">
+          <i className={`flag ${languages[locale].flag}`} />
+        </span>
+      ),
+      icon: <Icons.CaretDownOutlined iconSize="xs" />,
+      children: items,
+      popupClassName: 'language-picker-popup',
+    };
+  }, [languages, locale]);
diff --git a/superset-frontend/src/features/home/RightMenu.tsx 
b/superset-frontend/src/features/home/RightMenu.tsx
index 13946336f4..cfea2e4588 100644
--- a/superset-frontend/src/features/home/RightMenu.tsx
+++ b/superset-frontend/src/features/home/RightMenu.tsx
@@ -54,7 +54,7 @@ import DatabaseModal from 
'src/features/databases/DatabaseModal';
 import UploadDataModal from 'src/features/databases/UploadDataModel';
 import { uploadUserPerms } from 'src/views/CRUD/utils';
 import { useThemeContext } from 'src/theme/ThemeProvider';
-import LanguagePicker from './LanguagePicker';
+import { useLanguageMenuItems } from './LanguagePicker';
 import {
   ExtensionConfigs,
   GlobalMenuDataOptions,
@@ -366,6 +366,11 @@ const RightMenu = ({
     allowOSPreference: canDetectOSPreference(),
   });
 
+  const languageMenuItem = useLanguageMenuItems({
+    locale: navbarRight.locale || 'en',
+    languages: navbarRight.languages || {},
+  });
+
   // Build main menu items
   const menuItems = useMemo(() => {
     // Build menu items for the new dropdown
@@ -579,6 +584,10 @@ const RightMenu = ({
       items.push(themeMenuItem);
     }
 
+    if (navbarRight.show_language_picker && languageMenuItem) {
+      items.push(languageMenuItem);
+    }
+
     items.push({
       key: 'settings',
       label: t('Settings'),
@@ -594,6 +603,7 @@ const RightMenu = ({
     canSetMode,
     theme.colorPrimary,
     themeMenuItem,
+    languageMenuItem,
     dropdownItems,
     roles,
     settings,
@@ -661,12 +671,6 @@ const RightMenu = ({
         disabledOverflow
         items={menuItems}
       />
-      {navbarRight.show_language_picker && (
-        <LanguagePicker
-          locale={navbarRight.locale}
-          languages={navbarRight.languages}
-        />
-      )}
       {navbarRight.documentation_url && (
         <>
           <StyledAnchor

Reply via email to