Skip to content

Commit

Permalink
feat: release 4.0.0 (#860)
Browse files Browse the repository at this point in the history
* 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
silviuaavram and Kamil Socha committed Dec 20, 2019
1 parent 1d45829 commit bb699ea
Show file tree
Hide file tree
Showing 43 changed files with 5,685 additions and 965 deletions.
56 changes: 28 additions & 28 deletions .size-snapshot.json
Original file line number Diff line number Diff line change
@@ -1,59 +1,59 @@
{
"dist/downshift.cjs.js": {
"bundled": 84692,
"minified": 38317,
"gzipped": 9688
"bundled": 107604,
"minified": 50106,
"gzipped": 11240
},
"preact/dist/downshift.cjs.js": {
"bundled": 83400,
"minified": 37269,
"gzipped": 9582
"bundled": 106322,
"minified": 49068,
"gzipped": 11125
},
"preact/dist/downshift.umd.min.js": {
"bundled": 95821,
"minified": 31665,
"gzipped": 9759
"bundled": 118383,
"minified": 38903,
"gzipped": 11087
},
"preact/dist/downshift.umd.js": {
"bundled": 111340,
"minified": 38242,
"gzipped": 11495
"bundled": 134506,
"minified": 46407,
"gzipped": 12880
},
"dist/downshift.umd.min.js": {
"bundled": 100066,
"minified": 32983,
"gzipped": 10333
"bundled": 122618,
"minified": 40223,
"gzipped": 11625
},
"dist/downshift.umd.js": {
"bundled": 140975,
"minified": 47153,
"gzipped": 14120
"bundled": 164131,
"minified": 55319,
"gzipped": 15457
},
"dist/downshift.esm.js": {
"bundled": 84311,
"minified": 38008,
"gzipped": 9627,
"bundled": 107135,
"minified": 49711,
"gzipped": 11172,
"treeshaked": {
"rollup": {
"code": 629,
"code": 998,
"import_statements": 303
},
"webpack": {
"code": 2839
"code": 3280
}
}
},
"preact/dist/downshift.esm.js": {
"bundled": 83000,
"minified": 36941,
"gzipped": 9520,
"bundled": 105823,
"minified": 48643,
"gzipped": 11057,
"treeshaked": {
"rollup": {
"code": 630,
"code": 999,
"import_statements": 304
},
"webpack": {
"code": 2838
"code": 3279
}
}
}
Expand Down
352 changes: 230 additions & 122 deletions README.md

Large diffs are not rendered by default.

118 changes: 118 additions & 0 deletions docs/hooks/useCombobox.mdx
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'}>
&#8595;
</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>
Loading

0 comments on commit bb699ea

Please sign in to comment.