Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(hooks): add useSelect hook #747

Merged
merged 41 commits into from
Sep 10, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
bec5f12
update everything
silviuaavram Aug 18, 2019
4db1533
size snapshot update
silviuaavram Aug 18, 2019
dbddfa7
add code from downshift-hooks
silviuaavram Aug 18, 2019
6eb2c9d
removed and improved code
silviuaavram Aug 21, 2019
5d3aa63
small addition to useSelect readme
silviuaavram Aug 21, 2019
4392f5b
Merge branch 'master' into feat/useSelect-hook
silviuaavram Aug 21, 2019
a0c8bab
code improvements
silviuaavram Aug 24, 2019
c5ddbe2
utils changes
silviuaavram Aug 24, 2019
6f9e0c6
move state change types
silviuaavram Aug 25, 2019
712f040
change docs structure
silviuaavram Aug 25, 2019
b979777
removed the images in the docs
silviuaavram Aug 25, 2019
29fed27
revert params for a11y status
silviuaavram Aug 25, 2019
44dc4ea
readme update
silviuaavram Aug 25, 2019
9149ce5
some readme fixes
silviuaavram Aug 25, 2019
b6ae815
add stardust link
silviuaavram Aug 25, 2019
55c65db
change to getItemId
silviuaavram Aug 26, 2019
55823f2
first round of typings
silviuaavram Aug 26, 2019
230c260
some progress on typings
silviuaavram Aug 29, 2019
d1f105d
rename to selectItem and finish types
silviuaavram Aug 30, 2019
8cfbcf7
export useSelect
silviuaavram Aug 30, 2019
1901164
add rest to getLabel and getMenu
silviuaavram Aug 31, 2019
80cf150
removed some props from types
silviuaavram Aug 31, 2019
645f6e8
add selection without open
silviuaavram Sep 1, 2019
177f966
fixed debounce and add more tests
silviuaavram Sep 1, 2019
9c250c5
update readme with new key handler
silviuaavram Sep 1, 2019
1fe7c89
Merge branch 'master' into feat/useSelect-hook
silviuaavram Sep 2, 2019
877b8eb
add a revert for eslint
silviuaavram Sep 2, 2019
d9b1291
remove stateChangeTypes from prototype
silviuaavram Sep 3, 2019
0dc814a
add additional validation to enter keydown
silviuaavram Sep 3, 2019
e1c3a27
add environment as prop
silviuaavram Sep 3, 2019
c7d9fa3
moved ref for readability
silviuaavram Sep 3, 2019
c8a601d
split a11y message functions
silviuaavram Sep 3, 2019
e72e407
add prop type to rollup config
silviuaavram Sep 3, 2019
49f560a
merge master
silviuaavram Sep 4, 2019
3b40186
remove items and itemToString from return props
silviuaavram Sep 5, 2019
168c25e
moved items and styles out of mdx
silviuaavram Sep 7, 2019
210a999
merge master
silviuaavram Sep 7, 2019
4e238e9
stateReducer called before onChange props
silviuaavram Sep 7, 2019
fb5f7d8
docs improvements
silviuaavram Sep 8, 2019
7a0f763
split docs into Usage and UI Libraries
silviuaavram Sep 9, 2019
635345e
changes after personal review
silviuaavram Sep 10, 2019
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion .prettierignore
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
node_modules/
coverage/
dist/
storybook-static/
preact/
package-lock.json
package.json
64 changes: 32 additions & 32 deletions .size-snapshot.json
Original file line number Diff line number Diff line change
@@ -1,59 +1,59 @@
{
"dist/downshift.cjs.js": {
"bundled": 54715,
"minified": 24026,
"gzipped": 6601
"bundled": 81684,
"minified": 37987,
"gzipped": 9530
},
"preact/dist/downshift.cjs.js": {
"bundled": 53284,
"minified": 22876,
"gzipped": 6404
"bundled": 79932,
"minified": 36516,
"gzipped": 9354
},
"preact/dist/downshift.umd.min.js": {
"bundled": 66096,
"minified": 22452,
"gzipped": 7177
},
"dist/downshift.umd.min.js": {
"bundled": 70975,
"minified": 23865,
"gzipped": 7798
"bundled": 101249,
"minified": 35121,
"gzipped": 11501
},
"preact/dist/downshift.umd.js": {
"bundled": 79417,
"minified": 27880,
"gzipped": 8612
"bundled": 115089,
"minified": 41092,
"gzipped": 13013
},
"dist/downshift.umd.min.js": {
"bundled": 106251,
"minified": 36447,
"gzipped": 12109
},
"dist/downshift.umd.js": {
"bundled": 108817,
"minified": 36872,
"gzipped": 11363
"bundled": 144612,
"minified": 49969,
"gzipped": 15728
},
"dist/downshift.esm.js": {
"bundled": 54341,
"minified": 23735,
"gzipped": 6525,
"bundled": 80934,
"minified": 37317,
"gzipped": 9452,
"treeshaked": {
"rollup": {
"code": 296,
"import_statements": 296
"code": 533,
"import_statements": 420
},
"webpack": {
"code": 17927
"code": 27255
}
}
},
"preact/dist/downshift.esm.js": {
"bundled": 52930,
"minified": 22600,
"gzipped": 6332,
"bundled": 79215,
"minified": 35872,
"gzipped": 9265,
"treeshaked": {
"rollup": {
"code": 278,
"import_statements": 278
"code": 534,
"import_statements": 421
},
"webpack": {
"code": 17882
"code": 27264
}
}
}
Expand Down
20 changes: 10 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ for your use cases.
## This solution

This is a component that controls user interactions and state for you so you can
create autocomplete/dropdown/select/etc. components. It uses a [render
create autocomplete, dropdown, select, etc. components. It uses a [render
prop][use-a-render-prop] which gives you maximum flexibility with a minimal API
because you are responsible for the rendering of everything and you simply apply
props to what you're rendering.
Expand All @@ -50,22 +50,21 @@ harder to contribute to.
> NOTE: The original use case of this component is autocomplete, however the API
> is powerful and flexible enough to build things like dropdowns as well.

## The experiment
## The new React Hooks API

Downshift has proven to be a versatile React component which can be used not only
for single selection autocomplete, but also for single selection dropdown and
the multiple selection variations of each. In order to customise the behavior, the
developer needs to add more stateful logic to it, however, as each of the variations
differ in terms of design patterns.

We are now experimenting with adding a custom React hook for each use, so that there will
be no need of adding other stateful logic besides the hook. The experimentation repo is
[downshift-hooks][downshift-hooks]. The plan is to create each hook in that repo,
test it against Downshift principles and ARIA design patterns, and then finally add
each hook to this repo, so that importing them will be easy.
In the effort to provide out of the box solutions for each variation, a set of React
Hooks are about to be available as part of Downshift. Each hook will handle a specific
dropdown variation and be named accordingly: `useSelect`, `useAutocomplete`, etc.

If you like the idea, are passionate about React hooks or just want to be the cool kid from
the future that shapes Downshift, try out the new repo and share your feedback!
You can check the progress in the [hooks page][hooks-readme] and contribute! If you
have a custom `<select>` dropdown and want it to be functional and accessible, jump
directly to the already implemented [useSelect][useselect-readme].

## Table of Contents

Expand Down Expand Up @@ -1324,4 +1323,5 @@ MIT
[advanced-react]: https://courses.reacttraining.com/courses/enrolled/200086
[use-a-render-prop]: https://cdb.reacttraining.com/use-a-render-prop-50de598f11ce
[semver]: http://semver.org/
[downshift-hooks]: https://github.com/silviuavram/downshift-hooks
[hooks-readme]: https://github.com/downshift-js/downshift/blob/master/src/hooks
[useselect-readme]: https://github.com/downshift-js/downshift/blob/master/src/hooks/useSelect
40 changes: 40 additions & 0 deletions docs/useSelect/examples/html.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
const items = [
'Neptunium',
'Plutonium',
'Americium',
'Curium',
'Berkelium',
'Californium',
'Einsteinium',
'Fermium',
'Mendelevium',
'Nobelium',
'Lawrencium',
'Rutherfordium',
'Dubnium',
'Seaborgium',
'Bohrium',
'Hassium',
'Meitnerium',
'Darmstadtium',
'Roentgenium',
'Copernicium',
'Nihonium',
'Flerovium',
'Moscovium',
'Livermorium',
'Tennessine',
'Oganesson',
]
const menuStyles = {
maxHeight: '180px',
overflowY: 'auto',
width: '200px',
position: 'absolute',
margin: 0,
borderTop: 0,
background: 'white',
zIndex: 1000,
}

export {items, menuStyles}
86 changes: 86 additions & 0 deletions docs/useSelect/examples/html.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
---
name: Usage
menu: useSelect
route: /hooks/use-select/usage
---

import {Playground} from 'docz'
import {useSelect} from '../../../src'
import {items, menuStyles} from './html'

# useSelect

## Readme

The `useSelect` hook provides functionality and accessibility to a dropdown that should act as a HTML `<select>`, as described
by the corresponding [ARIA docs](https://www.w3.org/TR/wai-aria-practices/examples/listbox/listbox-collapsible.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 menu itself
and the collection of items that belong in the menu.

## HTML elements

A custom `<select>` element can be created with HTML elements such as: `<label>`, `<ul>`, `<li>` and `<button>`.
Using other HTML elements to create a custom `<select>` is useful for the custom styling of the widget, since the `<select>`
is notoriously difficult to be styled: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/select

In the example below, we use the `useSelect` hook and destructure from its result the getter props and state variables. These
are used in the following way:

| Returned prop | Element | Comments |
| ---------------------- | ---------------------- | ------------------------------------------------------------------------- |
| `getLabelProps` | `<label>` | Adds an `id` attribute to be used for `menu` and `triggerButton` |
| `getToggleButtonProps` | `<button>` | Controls the open state of the list. |
| `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` | before `<li>` elements | Only when it's true we render the `<li>` elements. |
| `highlightedIndex` | highlighted `<li>` | Used to style the highlighted item. |
| `selectedItem` | `<button>` | Used to render text equivalent of selected item on the button. |

## Playground

<Playground style={{height: '160px'}}>
{() => {
const DropdownSelect = () => {
const {
isOpen,
selectedItem,
getToggleButtonProps,
getLabelProps,
getMenuProps,
highlightedIndex,
getItemProps,
} = useSelect({items})
return (
<div>
<label {...getLabelProps()}>Choose an element:</label>
<button {...getToggleButtonProps()}>
{selectedItem || 'Elements'}
</button>
<ul {...getMenuProps()} style={menuStyles}>
{isOpen &&
items.map((item, index) => (
<li
style={
highlightedIndex === index
? {backgroundColor: '#bde4ff'}
: {}
}
key={`${item}${index}`}
{...getItemProps({item, index})}
>
{item}
</li>
))}
</ul>
</div>
)
}
return <DropdownSelect />
}}
</Playground>

## CodeSandbox

Until a direct link from Playground will work, codesandbox equivalent is at https://codesandbox.io/s/useselect-usage-53qfj
Loading