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