40316-vm/frontend/src/components/LanguageSwitcher.tsx
2026-06-23 14:09:24 +00:00

106 lines
3.5 KiB
TypeScript

import React, { useEffect, useState } from 'react';
import Select, { components, SingleValueProps, OptionProps } from 'react-select';
import { useTranslation } from 'react-i18next';
type LanguageOption = { label: string; value: string };
type Props = {
className?: string;
menuPlacement?: 'auto' | 'bottom' | 'top';
width?: number;
};
const LANGS: LanguageOption[] = [
{ value: 'pt', label: '🇵🇹 PT' },
{ value: 'en', label: '🇬🇧 EN' },
];
const Option = (props: OptionProps<LanguageOption, false>) => (
<components.Option {...props}>
<span className='flex items-center gap-1'>{props.data.label}</span>
</components.Option>
);
const SingleVal = (props: SingleValueProps<LanguageOption, false>) => (
<components.SingleValue {...props}>
<span className='flex items-center gap-1'>{props.data.label}</span>
</components.SingleValue>
);
const LanguageSwitcher: React.FC<Props> = ({ className = '', menuPlacement = 'bottom', width = 88 }) => {
const { i18n } = useTranslation();
const [mounted, setMounted] = useState(false);
const [selected, setSelected] = useState<LanguageOption>(LANGS[0]);
useEffect(() => {
const currentLanguage = i18n.resolvedLanguage || i18n.language || 'pt';
setSelected(LANGS.find((lang) => lang.value === currentLanguage) || LANGS[0]);
setMounted(true);
}, [i18n.language, i18n.resolvedLanguage]);
const handleChange = (opt: LanguageOption | null) => {
if (!opt) return;
setSelected(opt);
i18n.changeLanguage(opt.value);
};
if (!mounted) return null;
return (
<div className={className} style={{ width }}>
<Select
value={selected}
options={LANGS}
onChange={handleChange}
isSearchable={false}
menuPlacement={menuPlacement}
components={{
Option,
SingleValue: SingleVal,
IndicatorSeparator: () => null,
}}
styles={{
control: (base) => ({
...base,
minHeight: 28,
height: 28,
paddingTop: 0,
paddingBottom: 0,
borderColor: '#d1d5db',
cursor: 'pointer',
}),
valueContainer: (base) => ({
...base,
paddingTop: 0,
paddingBottom: 0,
paddingLeft: 6,
}),
indicatorsContainer: (base) => ({
...base,
height: 24,
}),
dropdownIndicator: (base) => ({
...base,
padding: 2,
}),
option: (base, state) => ({
...base,
paddingTop: 4,
paddingBottom: 4,
height: 26,
fontSize: '0.875rem',
backgroundColor: state.isFocused ? '#f3f4f6' : 'white',
color: '#111827',
}),
menu: (base) => ({
...base,
zIndex: 9999,
}),
}}
/>
</div>
);
};
export default LanguageSwitcher;