react-country-dropdown-cu
Version:
A simple country selector dropdown for React with flags and search
120 lines (110 loc) • 3.41 kB
JSX
import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
import Flag from 'react-world-flags';
import { countries as countryList } from './countries';
const CountryDropdown = ({ selectedCountry, onCountrySelect }) => {
const [selected, setSelected] = useState(
selectedCountry || { code: 'IN', shortName: 'India' }
);
const [open, setOpen] = useState(false);
const [searchTerm, setSearchTerm] = useState('');
const dropdownRef = useRef(null);
const toggleDropdown = () => setOpen(!open);
const filteredCountries = useMemo(() => {
return countryList.filter(({ code, shortName }) => {
const term = searchTerm.toLowerCase();
return (
shortName.toLowerCase().includes(term) ||
code.toLowerCase().includes(term)
);
});
}, [searchTerm]);
const handleCountrySelect = useCallback(
(country) => {
setSelected(country);
onCountrySelect?.(country);
setOpen(false);
setSearchTerm('');
},
[onCountrySelect]
);
const handleClickOutside = (e) => {
if (dropdownRef.current && !dropdownRef.current.contains(e.target)) {
setOpen(false);
}
};
useEffect(() => {
document.addEventListener('mousedown', handleClickOutside);
return () => document.removeEventListener('mousedown', handleClickOutside);
}, []);
return (
<div style={{ position: 'relative', width: '100%' }} ref={dropdownRef}>
<div
onClick={toggleDropdown}
role="button"
aria-haspopup="listbox"
aria-expanded={open}
tabIndex={0}
style={{
border: '1px solid #ccc',
padding: '10px',
borderRadius: '5px',
cursor: 'pointer',
display: 'flex',
alignItems: 'center',
gap: '10px',
}}
>
<Flag code={selected.code} style={{ width: '20px', height: '15px' }} />
<span>{selected.shortName}</span>
</div>
{open && (
<div
style={{
position: 'absolute',
zIndex: 10,
background: '#fff',
border: '1px solid #ccc',
borderRadius: '5px',
marginTop: '5px',
width: '100%',
maxHeight: '200px',
overflowY: 'auto',
}}
role="listbox"
>
<input
type="text"
placeholder="Search country"
value={searchTerm}
onChange={(e) => setSearchTerm(e.target.value)}
style={{
width: '100%',
padding: '8px',
borderBottom: '1px solid #ccc',
boxSizing: 'border-box',
}}
/>
{filteredCountries.map((country) => (
<div
key={country.code}
role="option"
aria-selected={country.code === selected.code}
onClick={() => handleCountrySelect(country)}
style={{
padding: '10px',
cursor: 'pointer',
display: 'flex',
alignItems: 'center',
gap: '10px',
}}
>
<Flag code={country.code} style={{ width: '20px', height: '15px' }} />
<span>{country.shortName}</span>
</div>
))}
</div>
)}
</div>
);
};
export default CountryDropdown;