fix: language select UI (#6890)

Co-authored-by: Johannes <johannes@formbricks.com>
This commit is contained in:
Dhruwang Jariwala
2025-11-28 01:40:03 +05:30
committed by GitHub
parent 2c18912f2f
commit 2698817adb
8 changed files with 31 additions and 20 deletions

View File

@@ -15,18 +15,16 @@ interface LanguageDropdownProps {
export const LanguageDropdown = ({ survey, setLanguage, locale }: LanguageDropdownProps) => {
const [showLanguageSelect, setShowLanguageSelect] = useState(false);
const languageDropdownRef = useRef(null);
const containerRef = useRef(null);
const enabledLanguages = getEnabledLanguages(survey.languages ?? []);
useClickOutside(languageDropdownRef, () => setShowLanguageSelect(false));
useClickOutside(containerRef, () => setShowLanguageSelect(false));
return (
enabledLanguages.length > 1 && (
<div className="relative">
<div className="relative" ref={containerRef}>
{showLanguageSelect && (
<div
className="absolute top-12 z-30 w-fit rounded-lg border bg-slate-900 p-1 text-sm text-white"
ref={languageDropdownRef}>
<div className="absolute top-12 z-30 max-h-64 max-w-48 overflow-auto rounded-lg border bg-slate-900 p-1 text-sm text-white">
{enabledLanguages.map((surveyLanguage) => (
<button
key={surveyLanguage.language.code}

View File

@@ -56,7 +56,7 @@ export function DefaultLanguageSelect({
});
}}
value={`${defaultLanguage?.code}`}>
<SelectTrigger className="xs:w-[180px] xs:text-sm w-full px-4 text-xs text-slate-800 dark:border-slate-400 dark:bg-slate-700 dark:text-slate-300">
<SelectTrigger className="w-full max-w-full truncate px-4 text-xs text-slate-800">
<SelectValue />
</SelectTrigger>
<SelectContent>

View File

@@ -57,7 +57,7 @@ export function LanguageIndicator({
</button>
{showLanguageDropdown ? (
<div
className="absolute right-0 z-30 mt-1 space-y-2 rounded-md bg-slate-900 p-1 text-xs text-white"
className="absolute right-0 z-30 mt-1 max-h-64 space-y-2 overflow-auto rounded-md bg-slate-900 p-1 text-xs text-white"
ref={languageDropdownRef}>
{surveyLanguages.map(
(language) =>

View File

@@ -66,10 +66,10 @@ export function LanguageSelect({ language, onLanguageChange, disabled, locale }:
disabled={disabled}
onClick={toggleDropdown}
variant="ghost">
<span className="mr-2">
<span className="mr-2 min-w-0 truncate">
{selectedOption ? getLabelForLocale(selectedOption) : t("common.select")}
</span>
<ChevronDown className="h-4 w-4" />
<ChevronDown className="h-4 w-4 shrink-0" />
</Button>
<div
className={`absolute right-0 z-30 mt-2 space-y-1 rounded-md bg-white p-1 shadow-lg ring-1 ring-black ring-opacity-5 ${isOpen ? "" : "hidden"}`}>
@@ -84,10 +84,10 @@ export function LanguageSelect({ language, onLanguageChange, disabled, locale }:
value={searchTerm}
/>
<div className="max-h-96 overflow-auto">
{filteredItems.map((item, index) => (
{filteredItems.map((item) => (
<button
className="block w-full cursor-pointer rounded-md px-4 py-2 text-left text-slate-700 hover:bg-slate-100 active:bg-blue-100"
key={index}
key={item.alpha2}
onClick={() => {
handleOptionSelect(item);
}}>

View File

@@ -19,7 +19,7 @@ export function LanguageToggle({ language, isChecked, onToggle, onEdit, locale }
const { t } = useTranslation();
return (
<div className="flex flex-col space-y-4">
<div className="flex items-center space-x-4">
<div className="flex max-w-96 items-center space-x-4">
<Switch
checked={isChecked}
id={`${language.code}-toggle`}
@@ -28,15 +28,18 @@ export function LanguageToggle({ language, isChecked, onToggle, onEdit, locale }
onToggle();
}}
/>
<Label className="font-medium text-slate-800" htmlFor={`${language.code}-toggle`}>
<Label className="truncate font-medium text-slate-800" htmlFor={`${language.code}-toggle`}>
{getLanguageLabel(language.code, locale)}
</Label>
{isChecked ? (
<p className="cursor-pointer text-xs text-slate-600 underline" onClick={onEdit}>
<button
className="truncate text-xs text-slate-600 underline hover:text-slate-800"
onClick={onEdit}
type="button">
{t("environments.surveys.edit.edit_translations", {
lang: getLanguageLabel(language.code, locale),
})}
</p>
</button>
) : null}
</div>
</div>

View File

@@ -91,7 +91,13 @@ describe("getProjectLanguages", () => {
expect(languages).toEqual(mockProject.languages);
expect(prisma.project.findUnique).toHaveBeenCalledWith({
where: { id: "testProjectId" },
select: { languages: true },
select: {
languages: {
orderBy: {
code: "asc",
},
},
},
});
});

View File

@@ -28,7 +28,11 @@ export const getProjectLanguages = reactCache(async (projectId: string): Promise
id: projectId,
},
select: {
languages: true,
languages: {
orderBy: {
code: "asc",
},
},
},
});
if (!project) {

View File

@@ -99,7 +99,7 @@ export function LanguageSwitch({
{showLanguageDropdown ? (
<div
className={cn(
"fb-bg-brand fb-text-on-brand fb-absolute fb-top-10 fb-space-y-2 fb-rounded-md fb-p-2 fb-text-xs",
"fb-bg-input-bg fb-text-heading fb-absolute fb-top-10 fb-max-h-64 fb-space-y-2 fb-overflow-auto fb-rounded-md fb-p-2 fb-text-xs",
dir === "rtl" ? "fb-left-8" : "fb-right-8"
)}
ref={languageDropdownRef}>
@@ -109,7 +109,7 @@ export function LanguageSwitch({
<button
key={surveyLanguage.language.id}
type="button"
className="fb-block fb-w-full fb-p-1.5 fb-text-left hover:fb-opacity-80"
className="fb-block fb-w-full fb-p-1.5 fb-rounded-md fb-text-left hover:fb-bg-brand hover:fb-text-on-brand fb-max-w-48 fb-truncate"
onClick={() => {
changeLanguage(surveyLanguage.language.code);
}}>