Light and flexible React hooks written in ReScript for building accessible listbox composed components, like menus, dropdown select and others.
Install it using the package manager of your preference:
npm install --save listboxkit
Or if your project uses yarn:
yarn add listboxkit
For ReScript projects, add listboxkit
as a dependency in your bsconfig.json
file:
{
"bs-dependencies": ["listboxkit"]
}
The main React hook for building listbox components is the useListbox
. Given a list of options, this hook will provide the state and the necessary event handlers for building your listbox.
const options = ["Red", "Green", "Blue"];
function ColorSelect() {
const {
highlightedIndex,
getOptionProps,
getContainerProps,
selectedIndexes
} = useListbox(options);
const selectedColors = selectedIndexes.map(i => options[i]).join(",")
return (
<div>
Selected color:{" "}
{selectedColors.length === 0 ? "no selected color" : selectedColors}.
<ul {...getContainerProps()}>
{options.map((option, index) => {
const highlighted = highlightedIndex === index;
return (
<li {...getOptionProps(index)}>
{highlighted ? `> ${option}` : option}
</li>
);
})}
</ul>
</div>
);
module ColorSelect {
let options = ["Red", "Green", "Blue"]
@react.component
let make = () => {
let {
highlightedIndex,
getOptionProps,
getContainerProps,
selectedIndexes
}: Listbox.listbox = Listbox.useListbox(options)
let { role, tabIndex, onKeyDown, onFocus, onBlur } = getContainerProps()
let selectedOption = selectedIndexes
-> Belt.Array.map(i => options -> Belt.Array.get(i))
-> Belt.Array.get(0)
-> Belt.getWithDefault("no selected color.")
let renderColorOption = (index, option) => {
let {
ariaSelected,
onClick,
role,
}: Listbox.optionProps = getOptionProps(index)
let highlighted = highlightedIndex == index
<li key=option onClick onKeyDown role ariaSelected>
{(highlighted ? `> ${option}` : option) |> React.string}
</li>
}
<div>
{React.string("Selected color :" ++ selectedOption)}
<ul role tabIndex onKeyDown onFocus onBlur>
{options
-> Belt.Array.mapWithIndex(renderOption)
-> React.array}
</ul>
</div>
}
}