Grouped items
- Grouped.tsx
- data/states-grouped.ts
import React, { useState } from 'react';
import { useCombobox, autocomplete, mergeGroupedItems } from '@szhsin/react-autocomplete';
import GROUPED from '../../data/states-grouped';
const Grouped = () => {
const [value, setValue] = useState<string>();
const [selected, setSelected] = useState<string>();
// It's up to you how to filter items based on the input value
const groups = value
? GROUPED.map(({ initial, states }) => ({
initial,
states: states.filter((item) => item.toLowerCase().includes(value.toLowerCase()))
})).filter((group) => group.states.length > 0)
: GROUPED;
const {
getFocusCaptureProps,
getLabelProps,
getInputProps,
getClearProps,
getToggleProps,
getListProps,
getItemProps,
open,
focusIndex,
isInputEmpty
} = useCombobox({
// The main hook always expects a one-dimensional array,
// and we provide a `mergeGroupedItems` utility to merge the groups.
items: mergeGroupedItems({ groups, getItemsInGroup: (group) => group.states }),
value,
onChange: setValue,
selected,
onSelectChange: setSelected,
feature: autocomplete({ select: true })
});
let itemIndex = -1;
return (
<div>
<label {...getLabelProps()} {...getFocusCaptureProps()}>
State
</label>
<div>
<input placeholder="Select or type..." {...getInputProps()} />
{!isInputEmpty && <button {...getClearProps()}>X</button>}
<button {...getToggleProps()}>{open ? '↑' : '↓'}</button>
</div>
<ul
{...getListProps()}
style={{
display: open ? 'block' : 'none',
position: 'absolute',
listStyle: 'none',
color: '#000',
background: '#fff',
overflow: 'auto',
maxHeight: 300,
margin: 0,
padding: 0
}}
>
{groups.length ? (
groups.map(({ initial, states }) => (
<React.Fragment key={initial}>
<li>{initial}</li>
{states.map((item) => {
// `itemIndex` should be the index within the flattened array of items.
itemIndex++;
return (
<li
key={item}
{...getItemProps({ item, index: itemIndex })}
style={{
background: focusIndex === itemIndex ? '#ddd' : 'none',
textDecoration: selected === item ? 'underline' : 'none'
}}
>
{item}
</li>
);
})}
</React.Fragment>
))
) : (
<li>No options</li>
)}
</ul>
</div>
);
};
export default Grouped;
export default [
{
initial: 'A',
states: ['Alabama', 'Alaska', 'Arizona', 'Arkansas']
},
{
initial: 'C',
states: ['California', 'Colorado', 'Connecticut']
},
{
initial: 'D',
states: ['Delaware']
},
{
initial: 'F',
states: ['Florida']
},
{
initial: 'G',
states: ['Georgia']
},
{
initial: 'H',
states: ['Hawaii']
},
{
initial: 'I',
states: ['Idaho', 'Illinois', 'Indiana', 'Iowa']
},
{
initial: 'K',
states: ['Kansas', 'Kentucky']
},
{
initial: 'L',
states: ['Louisiana']
},
{
initial: 'M',
states: [
'Maine',
'Maryland',
'Massachusetts',
'Michigan',
'Minnesota',
'Mississippi',
'Missouri',
'Montana'
]
},
{
initial: 'N',
states: [
'Nebraska',
'Nevada',
'New Hampshire',
'New Jersey',
'New Mexico',
'New York',
'North Carolina',
'North Dakota'
]
},
{
initial: 'O',
states: ['Ohio', 'Oklahoma', 'Oregon']
},
{
initial: 'P',
states: ['Pennsylvania']
},
{
initial: 'R',
states: ['Rhode Island']
},
{
initial: 'S',
states: ['South Carolina', 'South Dakota']
},
{
initial: 'T',
states: ['Tennessee', 'Texas']
},
{
initial: 'U',
states: ['Utah']
},
{
initial: 'V',
states: ['Vermont', 'Virginia']
},
{
initial: 'W',
states: ['Washington', 'West Virginia', 'Wisconsin', 'Wyoming']
}
];