Use a typeahead select where there are ten or more options (#28512)

Use typeahead for locale selector



Fix onFilter of SelectControl rather than removing it

Signed-off-by: John Gomersall <thegoms@gmail.com>
This commit is contained in:
john-gom 2024-04-18 21:18:00 +01:00 committed by GitHub
parent 89263f5255
commit 808926b63e
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 132 additions and 5 deletions

View file

@ -60,6 +60,32 @@ test.describe("Personal info with userprofile enabled", async () => {
await expect(page.getByText("Español")).toHaveCount(1); await expect(page.getByText("Español")).toHaveCount(1);
}); });
test("render long select options as typeahead", async ({ page }) => {
await login(page, user, "jdoe", realm);
await page.getByText("Alternate Language").click();
await page.waitForSelector("text=Italiano");
await page.locator("*:focus").press("Control+A");
await page.locator("*:focus").pressSequentially("S");
await expect(page.getByText("Italiano")).toHaveCount(0);
expect(page.getByText("Suomi")).toBeVisible();
expect(page.getByText('Create "S"')).not.toBeVisible();
});
test("render long list of locales as typeahead", async ({ page }) => {
await login(page, user, "jdoe", realm);
await page.locator("#locale").click();
await page.waitForSelector("text=Italiano");
await page.locator("*:focus").press("Control+A");
await page.locator("*:focus").pressSequentially("S");
await expect(page.getByText("Italiano")).toHaveCount(0);
expect(page.getByText("Suomi")).toBeVisible();
expect(page.getByText('Create "S"')).not.toBeVisible();
});
test("save user profile", async ({ page }) => { test("save user profile", async ({ page }) => {
await login(page, user, "jdoe", realm); await login(page, user, "jdoe", realm);

View file

@ -223,6 +223,71 @@
"email": {} "email": {}
}, },
"group": "group" "group": "group"
},
{
"name": "alternatelang",
"displayName": "Alternate Language",
"validations": {
"options": {
"options": [
"ar",
"ca",
"cs",
"de",
"en",
"es",
"fr",
"hu",
"fa",
"it",
"ja",
"lt",
"nl",
"no",
"pl",
"pt",
"ru",
"sk",
"sv",
"th",
"tr",
"uk",
"zh",
"fi"
]
}
},
"annotations": {
"inputType": "select",
"inputOptionLabels": {
"ar": "${locale_ar}",
"ca": "${locale_ca}",
"cs": "${locale_cs}",
"de": "${locale_de}",
"en": "${locale_en}",
"es": "${locale_es}",
"fr": "${locale_fr}",
"hu": "${locale_hu}",
"fa": "${locale_fa}",
"it": "${locale_it}",
"ja": "${locale_ja}",
"lt": "${locale_lt}",
"nl": "${locale_nl}",
"no": "${locale_no}",
"pl": "${locale_pl}",
"pt": "${locale_pt}",
"ru": "${locale_ru}",
"sk": "${locale_sk}",
"sv": "${locale_sv}",
"th": "${locale_th}",
"tr": "${locale_tr}",
"uk": "${locale_uk}",
"zh": "${locale_zh}",
"fi": "${locale_fi}"
}
},
"permissions": { "view": ["admin", "user"], "edit": ["admin", "user"] },
"group": "group"
} }
], ],
"groups": [ "groups": [

View file

@ -200,5 +200,34 @@
} }
} }
], ],
"identityFederationEnabled": true "identityFederationEnabled": true,
"internationalizationEnabled": true,
"supportedLocales": [
"de",
"no",
"fi",
"ru",
"lt",
"lv",
"fr",
"hu",
"zh-CN",
"sk",
"ca",
"sv",
"pt-BR",
"el",
"en",
"it",
"es",
"cs",
"ar",
"ja",
"fa",
"pl",
"da",
"nl",
"tr"
],
"defaultLocale": "en"
} }

View file

@ -72,7 +72,9 @@ export const SelectControl = <
const lowercasePrefix = prefix.toLowerCase(); const lowercasePrefix = prefix.toLowerCase();
return options return options
.filter((option) => .filter((option) =>
option.toString().toLowerCase().startsWith(lowercasePrefix), (isString(option) ? option : option.value)
.toLowerCase()
.startsWith(lowercasePrefix),
) )
.map((option) => ( .map((option) => (
<SelectOption key={key(option)} value={key(option)}> <SelectOption key={key(option)} value={key(option)}>

View file

@ -34,6 +34,7 @@ export const LocaleSelector = ({
label={t("selectALocale")} label={t("selectALocale")}
controller={{ defaultValue: "" }} controller={{ defaultValue: "" }}
options={locales} options={locales}
variant={locales.length >= 10 ? "typeahead" : "single"}
/> />
</FormProvider> </FormProvider>
); );

View file

@ -48,8 +48,6 @@ export const SelectComponent = (props: UserProfileFieldProps) => {
<Select <Select
toggleId={attribute.name} toggleId={attribute.name}
onToggle={(_event, b) => setOpen(b)} onToggle={(_event, b) => setOpen(b)}
isCreatable
onCreateOption={(value) => setValue(value, field)}
onSelect={(_, value) => { onSelect={(_, value) => {
const option = value.toString(); const option = value.toString();
setValue(option, field); setValue(option, field);
@ -60,7 +58,13 @@ export const SelectComponent = (props: UserProfileFieldProps) => {
selections={ selections={
field.value ? field.value : isMultiValue ? [] : t("choose") field.value ? field.value : isMultiValue ? [] : t("choose")
} }
variant={isMultiValue ? "typeaheadmulti" : "single"} variant={
isMultiValue
? "typeaheadmulti"
: options.length >= 10
? "typeahead"
: "single"
}
aria-label={t("selectOne")} aria-label={t("selectOne")}
isOpen={open} isOpen={open}
isDisabled={attribute.readOnly} isDisabled={attribute.readOnly}