feat: Use a Select control for the language select

This change updates the language selector in the user settings component
to use a Select control instead of a list of buttons.  The select
control will try and display the native language name instead of the
language code.  Fixes #21626

Signed-off-by: Stan Lewis <gashcrumb@gmail.com>
This commit is contained in:
Stan Lewis
2023-12-04 13:00:45 -05:00
parent 35185b1eee
commit 56b2fb0726
3 changed files with 31 additions and 47 deletions
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/plugin-user-settings': minor
---
Updated the user settings selector to use a select component that displays native language names instead of language codes if possible.
@@ -74,7 +74,10 @@ describe('UserSettingsLanguageToggle', () => {
await renderInTestApp(<UserSettingsLanguageToggle />);
fireEvent.click(screen.getByText('de'));
// open the select control
fireEvent.mouseDown(screen.getByText('English'));
// select the new language
fireEvent.click(screen.getByText('Deutsch'));
expect(mockLanguageApi.setLanguage).toHaveBeenCalledWith('de');
});
@@ -19,24 +19,16 @@ import {
useTranslationRef,
appLanguageApiRef,
} from '@backstage/core-plugin-api/alpha';
import ToggleButton from '@material-ui/lab/ToggleButton';
import ToggleButtonGroup from '@material-ui/lab/ToggleButtonGroup';
import {
ListItem,
ListItemText,
ListItemSecondaryAction,
Tooltip,
makeStyles,
} from '@material-ui/core';
import { userSettingsTranslationRef } from '../../translation';
import { useApi } from '@backstage/core-plugin-api';
import useObservable from 'react-use/lib/useObservable';
type TooltipToggleButtonProps = {
children: JSX.Element;
title: string;
value: string;
};
import { Select } from '@backstage/core-components';
const useStyles = makeStyles(theme => ({
container: {
@@ -71,21 +63,6 @@ const useStyles = makeStyles(theme => ({
},
}));
// ToggleButtonGroup uses React.children.map instead of context
// so wrapping with Tooltip breaks ToggleButton functionality.
const TooltipToggleButton = ({
children,
title,
value,
...props
}: TooltipToggleButtonProps) => (
<Tooltip placement="top" arrow title={title}>
<ToggleButton value={value} {...props}>
{children}
</ToggleButton>
</Tooltip>
);
/** @public */
export const UserSettingsLanguageToggle = () => {
const classes = useStyles();
@@ -104,13 +81,21 @@ export const UserSettingsLanguageToggle = () => {
return null;
}
const handleSetLanguage = (
_event: React.MouseEvent<HTMLElement>,
newLanguage: string | undefined,
) => {
const handleSetLanguage = (newLanguage: string | undefined) => {
languageApi.setLanguage(newLanguage);
};
const getLanguageDisplayName = (language: string) => {
try {
const names = new Intl.DisplayNames([language], {
type: 'language',
});
return names.of(language) || language;
} catch (err) {
return language;
}
};
return (
<ListItem
className={classes.list}
@@ -122,24 +107,15 @@ export const UserSettingsLanguageToggle = () => {
secondary={t('languageToggle.description')}
/>
<ListItemSecondaryAction className={classes.listItemSecondaryAction}>
<ToggleButtonGroup
exclusive
size="small"
value={currentLanguage}
onChange={handleSetLanguage}
>
{languages.map(language => {
return (
<TooltipToggleButton
key={language}
title={t('languageToggle.select', { language })}
value={language}
>
<>{language}</>
</TooltipToggleButton>
);
})}
</ToggleButtonGroup>
<Select
label=""
selected={currentLanguage}
items={languages.map(language => ({
label: getLanguageDisplayName(language),
value: language,
}))}
onChange={selectedItems => handleSetLanguage(selectedItems as string)}
/>
</ListItemSecondaryAction>
</ListItem>
);