-
Notifications
You must be signed in to change notification settings - Fork 932
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* feat: implement useCombobox (#812) * start implementation * more code reuse * create useCombobox * start implementation for handlers * remove not needed call * input handlers * progress on handlers * fix close on toggle button click * remove unneeded state change types * add example to docsite * focus input at toggle click + reactNative * add setInputValue * rename root to combobox + tests * add icon to button * add item tests * add more menu tests * finished input tests + initial state * finish testing * don't apply handlers if disabled * add tests for disabled cases * apply mozilla button close fix * initial default values small refactor * improvements for docs * updates to the docs and readme * readme updates * prop types validation not on production * readme correction * add ts typings * fix(TS): add generic to Downshift (#748) * fix a couple of typos * fix a type * final touches in README * readme update Co-authored-by: Kamil Socha <kamil.socha@netguru.co>
- Loading branch information
1 parent
1d45829
commit bb699ea
Showing
43 changed files
with
5,685 additions
and
965 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,118 @@ | ||
--- | ||
name: useCombobox | ||
menu: Hooks | ||
route: /hooks/use-combobox | ||
--- | ||
|
||
import {useState} from 'react' | ||
import {Playground} from 'docz' | ||
import {useCombobox} from '../../src' | ||
import {items, menuStyles, comboboxStyles, playgroundStyles} from '../utils' | ||
|
||
# useCombobox | ||
|
||
## Introduction | ||
|
||
The `useCombobox` hook provides functionality and accessibility to a dropdown | ||
that should act as an autocomplete `combobox` input with listbox, as described | ||
by the corresponding | ||
[ARIA docs](https://www.w3.org/TR/wai-aria-practices/examples/combobox/aria1.1pattern/listbox-combo.html). | ||
|
||
User should be allowed to perform a selection after opening the dropdown's menu. | ||
Only one item may be selected at a time. The widget should be built using a text | ||
label (optional but recommended), a button that toggles the menu, the combobox | ||
container, an input of type text inside the combobox container, the menu itself | ||
and the collection of items that belong in the menu. | ||
|
||
In the examples below, we use the `useCombobox` hook and destructure from its | ||
result the getter props and state variables. The hooks also has the | ||
`onInputValueChange` prop passed in order to filter the items in the list | ||
according to the input value. The getter props are used as follows: | ||
|
||
| Returned prop | Element | Comments | | ||
| ---------------------- | ---------- | ------------------------------------------------------------------------- | | ||
| `getLabelProps` | `<label>` | Adds an `id` attribute to be used for `menu` and `toggleButton` | | ||
| `getToggleButtonProps` | `<button>` | Controls the open state of the list. | | ||
| `getComboboxProps` | `<div>` | Container for `input` and `toggleButton`. | | ||
| `getInputProps` | `<input>` | Can be used to filter the options. Also displays the selected item. | | ||
| `getMenuProps` | `<ul>` | Makes list focusable, adds ARIA attributes and event handlers. | | ||
| `getItemProps` | `<li>` | Called with `index` and `item`, adds ARIA attributes and event listeners. | | ||
| `isOpen` | | Only when it's true we render the `<li>` elements. | | ||
| `highlightedIndex` | `<li>` | Used to style the highlighted item. | | ||
| `selectedItem` | `<button>` | Used to render text equivalent of selected item on the button. | | ||
|
||
For a complete documentation on all the returned props, hook props and more | ||
information check out the | ||
[Github Page](https://github.com/downshift-js/downshift/tree/master/src/hooks/useSelect). | ||
|
||
## Usage | ||
|
||
A `combobox` element can be created with HTML elements such as: `<label>`, | ||
`<ul>`, `<li>`, `<button>`, `<input>` and a `<div>` or something similar to | ||
contain the input and the toggle button. It is absolutely important to follow | ||
the HTML structure below, as it will allow all screen readers to properly work | ||
with the widget. Most importantly, the `<input>` needs to be contained by the | ||
combobox `<div>` and the `<ul>` needs to be at the same level with the combobox | ||
`<div>`. | ||
|
||
[CodeSandbox](https://codesandbox.io/s/usecombobox-usage-evufg) | ||
|
||
<Playground style={playgroundStyles}> | ||
{() => { | ||
const DropdownCombobox = () => { | ||
const [inputItems, setInputItems] = useState(items) | ||
const { | ||
isOpen, | ||
selectedItem, | ||
getToggleButtonProps, | ||
getLabelProps, | ||
getMenuProps, | ||
getInputProps, | ||
getComboboxProps, | ||
highlightedIndex, | ||
getItemProps, | ||
} = useCombobox({ | ||
items: inputItems, | ||
onInputValueChange: ({inputValue}) => { | ||
setInputItems( | ||
items.filter(item => | ||
item.toLowerCase().startsWith(inputValue.toLowerCase()), | ||
), | ||
) | ||
}, | ||
}) | ||
|
||
return ( | ||
<> | ||
<label {...getLabelProps()}>Choose an element:</label> | ||
<div style={comboboxStyles} {...getComboboxProps()}> | ||
<input {...getInputProps()} /> | ||
<button {...getToggleButtonProps()} aria-label={'toggle menu'}> | ||
↓ | ||
</button> | ||
</div> | ||
<ul {...getMenuProps()} style={menuStyles}> | ||
{isOpen && | ||
inputItems.map((item, index) => ( | ||
<li | ||
style={ | ||
highlightedIndex === index | ||
? {backgroundColor: '#bde4ff'} | ||
: {} | ||
} | ||
key={`${item}${index}`} | ||
{...getItemProps({item, index})} | ||
> | ||
{item} | ||
</li> | ||
))} | ||
</ul> | ||
</> | ||
) | ||
} | ||
|
||
return <DropdownCombobox /> | ||
|
||
}} | ||
|
||
</Playground> |
Oops, something went wrong.