# Technical Documentation: downshift-js/downshift

> ℹ️ **Provenance:** Multi-Tier Ingestion · [CodeWiki Reference](https://codewiki.google/github.com/downshift-js/downshift)

### Overview (`README.md`)

<h1 align="center">
  downshift 🏎
  <br>
  <img src="https://raw.githubusercontent.com/downshift-js/downshift/master/other/public/logo/downshift.svg" alt="downshift logo" title="downshift logo" width="300">
  <br>
</h1>
<p align="center" style="font-size: 1.2rem;">Primitives to build simple, flexible, WAI-ARIA compliant React
autocomplete, combobox or select dropdown components.</p>

> [Read the docs](https://downshift-js.com) |
> [See the intro blog post](https://kentcdodds.com/blog/introducing-downshift-for-react)
> |
> [Listen to the Episode 79 of the Full Stack Radio podcast](https://fullstackradio.com/79)

<hr />

[![Build Status][build-badge]][build]
[![Code Coverage][coverage-badge]][coverage]
[![downloads][downloads-badge]][npmcharts] [![version][version-badge]][package]
[![MIT License][license-badge]][license]

[](#contributors)
[![PRs Welcome][prs-badge]][prs] [![Chat][chat-badge]][chat]
[![Code of Conduct][coc-badge]][coc]
[![Join the community on Spectrum][spectrum-badge]][spectrum]

[![Supports React and Preact][react-badge]][react]
[![size][size-badge]][unpkg-dist] [![gzip size][gzip-badge]][unpkg-dist]
[![module formats: umd, cjs, and es][module-formats-badge]][unpkg-dist]

## The problem

You need an autocomplete, a combobox or a select experience in your application
and you want it to be accessible. You also want it to be simple and flexible to
account for your use cases. Finally, it should follow the [ARIA][aria] design
pattern for a [combobox][combobox-aria-example] or a
[select][select-aria-example], depending on your use case.

## This solution

The library offers a couple of solutions. The first solution, which is the one
we recommend you to try first, is a set of React hooks. Each hook provides the
stateful logic needed to make the corresponding component functional and
accessible. Navigate to the documentation for each by using the links in the
list below.

- [useSelect][useselect-readme] for a custom select component.
- [useCombobox][combobox-readme] for a combobox or autocomplete input.
- [useTagGroup][tag-group-readme] for a tag group component. Also useful to
  build a multiple selection combobox or select component with tags.

The second solution is the `Downshift` component, which can also be used to
create accessible combobox and select components, providing the logic in the
form of a render prop. It served as inspiration for developing the hooks and it
has been around for a while. It established a successful pattern for making
components accessible and functional while giving developers complete freedom
when building the UI.

Both _useSelect_ and _useCombobox_ support the latest ARIA combobox patterns for
W3C, which _Downshift_ does not. Consequently, we strongly recommend the you use
the hooks. The hooks have been migrated to the ARIA 1.2 combobox pattern in the
version 7 of _downshift_. There is a [Migration Guide][migration-guide-v7] that
documents the changes introduced in version 7.

The `README` on this page covers only the component while each hook has its own
`README` page. You can navigate to the [hooks page][hooks-readme] or go directly
to the hook you need by using the links in the list above.

For examples on how to use the hooks or the Downshift component, check out our
[docsite][docsite]!

**🚨 Use the Downshift hooks 🚨**

If you are new to the library, consider the _useSelect_ and _useCombobox_ hooks
as the first option. As mentioned above, the hooks benefit from the updated ARIA
patterns and are actively maintained and improved. If there are use cases that
are supported by the _Downshift_ component and not by the hooks, please create
an issue in our repo. The _Downshift_ component is going to be removed
completely once the hooks become mature.

### Downshift

This is a component that controls user interactions and state for you so you can
create autocomplete, combobox or select dropdown 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.

This differs from other solutions which render things for their use case and
then expose many options to allow for extensibility resulting in a bigger API
that is less flexible as well as making the implementation more complicated and
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.

## Table of Contents




- [Installation](#installation)
- [Usage](#usage)
- [Basic Props](#basic-props)
  - [children](#children)
  - [itemToString](#itemtostring)
  - [onChange](#onchange)
  - [stateReducer](#statereducer)
- [Advanced Props](#advanced-props)
  - [initialSelectedItem](#initialselecteditem)
  - [initialInputValue](#initialinputvalue)
  - [initialHighlightedIndex](#initialhighlightedindex)
  - [initialIsOpen](#initialisopen)
  - [defaultHighlightedIndex](#defaulthighlightedindex)
  - [defaultIsOpen](#defaultisopen)
  - [selectedItemChanged](#selecteditemchanged)
  - [getA11yStatusMessage](#geta11ystatusmessage)
  - [onSelect](#onselect)
  - [onStateChange](#onstatechange)
  - [onInputValueChange](#oninputvaluechange)
  - [itemCount](#itemcount)
  - [highlightedIndex](#highlightedindex)
  - [inputValue](#inputvalue)
  - [isOpen](#isopen)
  - [selectedItem](#selecteditem)
  - [id](#id)
  - [inputId](#inputid)
  - [labelId](#labelid)
  - [menuId](#menuid)
  - [getItemId](#getitemid)
  - [environment](#environment)
  - [onOuterClick](#onouterclick)
  - [scrollIntoView](#scrollintoview)
- [stateChangeTypes](#statechangetypes)
- [Control Props](#control-props)
- [Children Function](#children-function)
  - [prop getters](#prop-getters)
  - [actions](#actions)
  - [state](#state)
  - [props](#props)
- [Event Handlers](#event-handlers)
  - [default handlers](#default-handlers)
  - [customizing handlers](#customizing-handlers)
- [Utilities](#utilities)
  - [resetIdCounter](#resetidcounter)
- [React Native](#react-native)
  - [Gotchas](#gotchas)
- [Advanced React Component Patterns course](#advanced-react-component-patterns-course)
- [Examples](#examples)
- [FAQ](#faq)
- [Inspiration](#inspiration)
- [Other Solutions](#other-solutions)
- [Bindings for ReasonML](#bindings-for-reasonml)
- [Contributors](#contributors)
- [LICENSE](#license)



## Installation

This module is distributed via [npm][npm] which is bundled with [node][node] and
should be installed as one of your project's `dependencies`:

```
npm install --save downshift
```

> This package also depends on `react`. Please make sure you have it installed
> as well.

> Note also this library supports `preact` out of the box. If you are using
> `preact` then use the corresponding module in the `preact/dist` folder. You
> can even `import Downshift from 'downshift/preact'` 👍

## Usage

> [Try it out in the browser][code-sandbox-try-it-out]

```
/* Detailed source-code truncated for AI context efficiency. */
```

There is also an [example without getRootProps][code-sandbox-no-get-root-props].

> Warning: The example without `getRootProps` is not fully accessible with
> screen readers as it's not possible to achieve the HTML structure suggested by
> ARIA. We recommend following the example with `getRootProps`. Examples on how
> to use `Downshift` component with and without `getRootProps` are on the
> [docsite](https://downshift-js.com/).

`Downshift` is the only component exposed by this package. It doesn't render
anything itself, it just calls the render function and renders that. ["Use a
render prop!"][use-a-render-prop]!
`<Downshift>{downshift => <div>/* your JSX here! */</div>}</Downshift>`.

## Basic Props

This is the list of props that you should probably know about. There are some
[advanced props](#advanced-props) below as well.

### children

> `function({})` | _required_

This is called with an object. Read more about the properties of this object in
the section "[Children Function](#children-function)".

### itemToString

> `function(item: any)` | defaults to: `item => (item ? String(item) : '')`

If your items are stored as, say, objects instead of strings, downshift still
needs a string representation for each one (e.g., to set `inputValue`).

**Note:** This callback _must_ include a null check: it is invoked with `null`
whenever the user abandons input via `<Esc>`.

### onChange

> `function(selectedItem: any, stateAndHelpers: object)` | optional, no useful
> default

Called when the selected item changes, either by the user selecting an item or
the user clearing the selection. Called with the item that was selected or
`null` and the new state of `downshift`. (see `onStateChange` for more info on
`stateAndHelpers`).

- `selectedItem`: The item that was just selected. `null` if the selection was
  cleared.
- `stateAndHelpers`: This is the same thing your `children` function is called
  with (see [Children Function](#children-function))

### stateReducer

> `function(state: object, changes: object)` | optional

**🚨 This is a really handy power feature 🚨**

This function will be called each time `downshift` sets its internal state (or
calls your `onStateChange` handler for control props). It allows you to modify
the state change that will take place which can give you fine grain control over
how the component interacts with user updates without having to use
[Control Props](#control-props). It gives you the current state and the state
that will be set, and you return the state that you want to set.

- `state`: The full current state of downshift.
- `changes`: These are the properties that are about to change. This also has a
  `type` property which you can learn more about in the
  [`stateChangeTypes`](#statechangetypes) section.

```jsx
const ui = (
  <Downshift stateReducer={stateReducer}>{/* your callback */}</Downshift>
)

function stateReducer(state, changes) {
  // this prevents the menu from being closed when the user
  // selects an item with a keyboard or mouse
  switch (changes.type) {
    case Downshift.stateChangeTypes.keyDownEnter:
    case Downshift.stateChangeTypes.clickItem:
      return {
        ...changes,
        isOpen: state.isOpen,
        highlightedIndex: state.highlightedIndex,
      }
    default:
      return changes
  }
}
```

> NOTE: This is only called when state actually changes. You should not attempt
> to use this to handle events. If you wish to handle events, put your event
> handlers directly on the elements (make sure to use the prop getters though!
> For example: `<input onBlur={handleBlur} />` should be
> `<input {...getInputProps({onBlur: handleBlur})} />`). Also, your reducer
> function should be "pure." This means it should do nothing other than return
> the state changes you want to have happen.

## Advanced Props

### initialSelectedItem

> `any` | defaults to `null`

Pass an item or an array of items that should be selected when downshift is
initialized.

### initialInputValue

> `string` | defaults to `''`

This is the initial input value when downshift is initialized.

### initialHighlightedIndex

> `number`/`null` | defaults to `defaultHighlightedIndex`

This is the initial value to set the highlighted index to when downshift is
initialized.

### initialIsOpen

> `boolean` | defaults to `defaultIsOpen`

This is the initial `isOpen` value when downshift is initialized.

### defaultHighlightedIndex

> `number`/`null` | defaults to `null`

This is the value to set the `highlightedIndex` to anytime downshift is reset,
when the selection is cleared, when an item is selected or when the inputValue
is changed.

### defaultIsOpen

> `boolean` | defaults to `false`

This is the value to set the `isOpen` to anytime downshift is reset, when the
the selection is cleared, or when an item is selected.

### selectedItemChanged

> `function(prevItem: any, item: any)` | defaults to:
> `(prevItem, item) => (prevItem !== item)`

Used to determine if the new `selectedItem` has changed compared to the previous
`selectedItem` and properly update Downshift's internal state.

### getA11yStatusMessage

> `function({/* see below */})` | default messages provided in English

This function is passed as props to a `Status` component nested within and
allows you to create your own assertive ARIA statuses.

A default `getA11yStatusMessage` function is provided that will check
`resultCount` and return "No results are available." or if there are results ,
"`resultCount` results are available, use up and down arrow keys to navigate.
Press Enter key to select."

The object you are passed to generate your status message has the following
properties:



| property              | type            | description                                                                                  |
| --------------------- | --------------- | -------------------------------------------------------------------------------------------- |
| `highlightedIndex`    | `number`/`null` | The currently highlighted index                                                              |
| `highlightedItem`     | `any`           | The value of the highlighted item                                                            |
| `inputValue`          | `string`        | The current input value                                                                      |
| `isOpen`              | `boolean`       | The `isOpen` state                                                                           |
| `itemToString`        | `function(any)` | The `itemToString` function (see props) for getting the string value from one of the options |
| `previousResultCount` | `number`        | The total items showing in the dropdown the last time the status was updated                 |
| `resultCount`         | `number`        | The total items showing in the dropdown                                                      |
| `selectedItem`        | `any`           | The value of the currently selected item                                                     |

### onSelect

> `function(selectedItem: any, stateAndHelpers: object)` | optional, no useful
> default

Called when the user selects an item, regardless of the previous selected item.
Called with the item that was selected and the new state of `downshift`. (see
`onStateChange` for more info on `stateAndHelpers`).

- `selectedItem`: The item that was just selected
- `stateAndHelpers`: This is the same thing your `children` function is called
  with (see [Children Function](#children-function))

### onStateChange

> `function(changes: object, stateAndHelpers: object)` | optional, no useful
> default

This function is called anytime the internal state changes. This can be useful
if you're using downshift as a "controlled" component, where you manage some or
all of the state (e.g., isOpen, selectedItem, highlightedIndex, etc) and then
pass it as props, rather than letting downshift control all its state itself.
The parameters both take the shape of internal state
(`{highlightedIndex: number, inputValue: string, isOpen: boolean, selectedItem: any}`)
but differ slightly.

- `changes`: These are the properties that actually have changed since the last
  state change. This also has a `type` property which you can learn more about
  in the [`stateChangeTypes`](#statechangetypes) section.
- `stateAndHelpers`: This is the exact same thing your `children` function is
  called with (see [Children Function](#children-function))

> Tip: This function will be called any time _any_ state is changed. The best
> way to determine whether any particular state was changed, you can use
> `changes.hasOwnProperty('propName')`.

> NOTE: This is only called when state actually changes. You should not attempt
> to use this to handle events. If you wish to handle events, put your event
> handlers directly on the elements (make sure to use the prop getters though!
> For example: `<input onBlur={handleBlur} />` should be
> `<input {...getInputProps({onBlur: handleBlur})} />`).

### onInputValueChange

> `function(inputValue: string, stateAndHelpers: object)` | optional, no useful
> default

Called whenever the input value changes. Useful to use instead or in combination
of `onStateChange` when `inputValue` is a controlled prop to
[avoid issues with cursor positions](https://github.com/downshift-js/downshift/issues/217).

- `inputValue`: The current value of the input
- `stateAndHelpers`: This is the same thing your `children` function is called
  with (see [Children Function](#children-function))

### itemCount

> `number` | optional, defaults the number of times you call getItemProps

This is useful if you're using some kind of virtual listing component for
"windowing" (like
[`react-virtualized`](https://github.com/bvaughn/react-virtualized)).

### highlightedIndex

> `number` | **control prop** (read more about this in
> [the Control Props section](#control-props))

The index that should be highlighted

### inputValue

> `string` | **control prop** (read more about this in
> [the Control Props section](#control-props))

The value the input should have

### isOpen

> `boolean` | **control prop** (read more about this in
> [the Control Props section](#control-props))

Whether the menu should be considered open or closed. Some aspects of the
downshift component respond differently based on this value (for example, if
`isOpen` is true when the user hits "Enter" on the input field, then the item at
the `highlightedIndex` item is selected).

### selectedItem

> `any`/`Array(any)` | **control prop** (read more about this in
> [the Control Props section](#control-props))

The currently selected item.

### id

> `string` | defaults to a generated ID

You should not normally need to set this prop. It's only useful if you're server
rendering items (which each have an `id` prop generated based on the `downshift`
`id`). For more information see the `FAQ` below.

### inputId

> `string` | defaults to a generated ID

Used for `aria` attributes and the `id` prop of the element (`input`) you use
[`getInputProps`](#getinputprops) with.

### labelId

> `string` | defaults to a generated ID

Used for `aria` attributes and the `id` prop of the element (`label`) you use
[`getLabelProps`](#getlabelprops) with.

### menuId

> `string` | defaults to a generated ID

Used for `aria` attributes and the `id` prop of the element (`ul`) you use
[`getMenuProps`](#getmenuprops) with.

### getItemId

> `function(index)` | defaults to a function that generates an ID based on the
> index

Used for `aria` attributes and the `id` prop of the element (`li`) you use
[`getInputProps`](#getinputprops) with.

### environment

> `window` | defaults to `window`

This prop is only useful if you're rendering downshift within a different
`window` context from where your JavaScript is running; for example, an iframe
or a shadow-root. If the given context is lacking `document` and/or
`add|removeEventListener` on its prototype (as is the case for a shadow-root)
then you will need to pass in a custom object that is able to provide
[access to these properties](https://gist.github.com/Rendez/1dd55882e9b850dd3990feefc9d6e177)
for downshift.

### onOuterClick

> `function(stateAndHelpers: object)` | optional

A helper callback to help control internal state of downshift like `isOpen` as
mentioned in [this issue](https://github.com/downshift-js/downshift/issues/206).
The same behavior can be achieved using `onStateChange`, but this prop is
provided as a helper because it's a fairly common use-case if you're controlling
the `isOpen` state:

```jsx
const ui = (
  <Downshift
    isOpen={this.state.menuIsOpen}
    onOuterClick={() => this.setState({menuIsOpen: false})}
  >
    {/* your callback */}
  </Downshift>
)
```

This callback will only be called if `isOpen` is `true`.

### scrollIntoView

> `function(node: HTMLElement, menuNode: HTMLElement)` | defaults to internal
> implementation

This allows you to customize how the scrolling works when the highlighted index
changes. It receives the node to be scrolled to and the root node (the root node
you render in downshift). Internally we use
[`compute-scroll-into-view`](https://www.npmjs.com/package/compute-scroll-into-view)
so if you use that package then you wont be adding any additional bytes to your
bundle :)

## stateChangeTypes

There are a few props that expose changes to state
([`onStateChange`](#onstatechange) and [`stateReducer`](#statereducer)). For you
to make the most of these APIs, it's important for you to understand why state
is being changed. To accomplish this, there's a `type` property on the `changes`
object you get. This `type` corresponds to a `Downshift.stateChangeTypes`
property.

The list of all possible values this `type` property can take is defined in
[this file](https://github.com/downshift-js/downshift/blob/master/src/stateChangeTypes.js)
and is as follows:

- `Downshift.stateChangeTypes.unknown`
- `Downshift.stateChangeTypes.mouseUp`
- `Downshift.stateChangeTypes.itemMouseEnter`
- `Downshift.stateChangeTypes.keyDownArrowUp`
- `Downshift.stateChangeTypes.keyDownArrowDown`
- `Downshift.stateChangeTypes.keyDownEscape`
- `Downshift.stateChangeTypes.keyDownEnter`
- `Downshift.stateChangeTypes.keyDownHome`
- `Downshift.stateChangeTypes.keyDownEnd`
- `Downshift.stateChangeTypes.clickItem`
- `Downshift.stateChangeTypes.blurInput`
- `Downshift.stateChangeTypes.changeInput`
- `Downshift.stateChangeTypes.keyDownSpaceButton`
- `Downshift.stateChangeTypes.clickButton`
- `Downshift.stateChangeTypes.blurButton`
- `Downshift.stateChangeTypes.controlledPropUpdatedSelectedItem`
- `Downshift.stateChangeTypes.touchEnd`

See [`stateReducer`](#statereducer) for a concrete example on how to use the
`type` property.

## Control Props

downshift manages its own state internally and calls your `onChange` and
`onStateChange` handlers with any relevant changes. The state that downshift
manages includes: `isOpen`, `selectedItem`, `inputValue`, and
`highlightedIndex`. Your Children function (read more below) can be used to
manipulate this state and can likely support many of your use cases.

However, if more control is needed, you can pass any of these pieces of state as
a prop (as indicated above) and that state becomes controlled. As soon as
`this.props[statePropKey] !== undefined`, internally, `downshift` will determine
its state based on your prop's value rather than its own internal state. You
will be required to keep the state up to date (this is where `onStateChange`
comes in really handy), but you can also control the state from anywhere, be
that state from other components, `redux`, `react-router`, or anywhere else.

> Note: This is very similar to how normal controlled components work elsewhere
> in react (like `<input />`). If you want to learn more about this concept, you
> can learn about that from this the
> [Advanced React Component Patterns course](#advanced-react-component-patterns-course)

## Children Function

This is where you render whatever you want to based on the state of `downshift`.
You use it like so:

```javascript
const ui = (
  <Downshift>
    {downshift => (
      // use downshift utilities and state here, like downshift.isOpen,
      // downshift.getInputProps, etc.
      <div>{/* more jsx here */}</div>
    )}
  </Downshift>
)
```

The properties of this `downshift` object can be split into three categories as
indicated below:

### prop getters

> See
> [the blog post about prop getters](https://kentcdodds.com/blog/how-to-give-rendering-control-to-users-with-prop-getters)

> NOTE: These prop-getters provide important `aria-` attributes which are very
> important to your component being accessible. It's recommended that you
> utilize these functions and apply the props they give you to your components.

These functions are used to apply props to the elements that you render. This
gives you maximum flexibility to render what, when, and wherever you like. You
call these on the element in question (for example:
`<input {...getInputProps()}`)). It's advisable to pass all your props to that
function rather than applying them on the element yourself to avoid your props
being overridden (or overriding the props returned). For example:
`getInputProps({onKeyUp(event) {console.log(event)}})`.



| property               | type              | description                                                                                    |
| ---------------------- | ----------------- | ---------------------------------------------------------------------------------------------- |
| `getToggleButtonProps` | `function({})`    | returns the props you should apply to any menu toggle button element you render.               |
| `getInputProps`        | `function({})`    | returns the props you should apply to the `input` element that you render.                     |
| `getItemProps`         | `function({})`    | returns the props you should apply to any menu item elements you render.                       |
| `getLabelProps`        | `function({})`    | returns the props you should apply to the `label` element that you render.                     |
| `getMenuProps`         | `function({},{})` | returns the props you should apply to the `ul` element (or root of your menu) that you render. |
| `getRootProps`         | `function({},{})` | returns the props you should apply to the root element that you render. It can be optional.    |

#### `getRootProps`

<details>

<summary>
  If you cannot render a div as the root element, then read this
</summary>

Most of the time, you can just render a `div` yourself and `Downshift` will
apply the props it needs to do its job (and you don't need to call this
function). However, if you're rendering a composite component (custom component)
as the root element, then you'll need to call `getRootProps` and apply that to
your root element (downshift will throw an error otherwise).

There are no required properties for this method.

Optional properties:

- `refKey`: if you're rendering a composite component, that component will need
  to accept a prop which it forwards to the root DOM element. Commonly, folks
  call this `innerRef`. So you'd call: `getRootProps({refKey: 'innerRef'})` and
  your composite component would forward like: `<div ref={props.innerRef} />`.
  It defaults to `ref`.

If you're rendering a composite component, `Downshift` checks that
`getRootProps` is called and that `refKey` is a prop of the returned composite
component. This is done to catch common causes of errors but, in some cases, the
check could fail even if the ref is correctly forwarded to the root DOM
component. In these cases, you can provide the object
`{suppressRefError : true}` as the second argument to `getRootProps` to
completely bypass the check.\
**Please use it with extreme care and only if you are absolutely sure that the
ref is correctly forwarded otherwise `Downshift` will unexpectedly fail.**\
See [#235](https://github.com/downshift-js/downshift/issues/235) for the
discussion that lead to this.

</details>

#### `getInputProps`

This method should be applied to the `input` you render. It is recommended that
you pass all props as an object to this method which will compose together any
of the event handlers you need to apply to the `input` while preserving the ones
that `downshift` needs to apply to make the `input` behave.

There are no required properties for this method.

Optional properties:

- `disabled`: If this is set to true, then no event handlers will be returned
  from `getInputProps` and a `disabled` prop will be returned (effectively
  disabling the input).

- `aria-label`: By default the menu will add an `aria-labelledby` that refers to
  the `<label>` rendered with `getLabelProps`. However, if you provide
  `aria-label` to give a more specific label that describes the options
  available, then `aria-labelledby` will not be provided and screen readers can
  use your `aria-label` instead.

#### `getLabelProps`

This method should be applied to the `label` you render. It is useful for
ensuring that the `for` attribute on the `<label>` (`htmlFor` as a react prop)
is the same as the `id` that appears on the `input`. If no `htmlFor` is provided
(the normal case) then an ID will be generated and used for the `input` and the
`label` `for` attribute.

There are no required properties for this method.

> Note: For accessibility purposes, calling this method is highly recommended.

#### `getMenuProps`

This method should be applied to the element which contains your list of items.
Typically, this will be a `<div>` or a `<ul>` that surrounds a `map` expression.
This handles the proper ARIA roles and attributes.

Optional properties:

- `refKey`: if you're rendering a composite component, that component will need
  to accept a prop which it forwards to the root DOM element. Commonly, folks
  call this `innerRef`. So you'd call: `getMenuProps({refKey: 'innerRef'})` and
  your composite component would forward like: `<ul ref={props.innerRef} />`.
  However, if you are just rendering a primitive component like `<div>`, there
  is no need to specify this property. It defaults to `ref`.

  Please keep in mind that menus, for accessibility purposes, should always be
  rendered, regardless of whether you hide it or not. Otherwise, `getMenuProps`
  may throw error if you unmount and remount the menu.

- `aria-label`: By default the menu will add an `aria-labelledby` that refers to
  the `<label>` rendered with `getLabelProps`. However, if you provide
  `aria-label` to give a more specific label that describes the options
  available, then `aria-labelledby` will not be provided and screen readers can
  use your `aria-label` instead.

In some cases, you might want to completely bypass the `refKey` check. Then you
can provide the object `{suppressRefError : true}` as the second argument to
`getMenuProps`. **Please use it with extreme care and only if you are absolutely
sure that the ref is correctly forwarded otherwise `Downshift` will unexpectedly
fail.**

```jsx
<ul {...getMenuProps()}>
  {!isOpen
    ? null
    : items.map((item, index) => (
        <li {...getItemProps({item, index, key: item.id})}>{item.name}</li>
      ))}
</ul>
```

> Note that for accessibility reasons it's best if you always render this
> element whether or not downshift is in an `isOpen` state.

#### `getItemProps`

The props returned from calling this function should be applied to any menu
items you render.

**This is an impure function**, so it should only be called when you will
actually be applying the props to an item.

<details>

<summary>What do you mean by impure function?</summary>

Basically just don't do this:

```jsx
items.map(item => {
  const props = getItemProps({item}) // we're calling it here
  if (!shouldRenderItem(item)) {
    return null // but we're not using props, and downshift thinks we are...
  }
  return <div {...props} />
})
```

Instead, you could do this:

```jsx
items.filter(shouldRenderItem).map(item => <div {...getItemProps({item})} />)
```

</details>

Required properties:

- `item`: this is the item data that will be selected when the user selects a
  particular item.

Optional properties:

- `index`: This is how `downshift` keeps track of your item when updating the
  `highlightedIndex` as the user keys around. By default, `downshift` will
  assume the `index` is the order in which you're calling `getItemProps`. This
  is often good enough, but if you find odd behavior, try setting this
  explicitly. It's probably best to be explicit about `index` when using a
  windowing library like `react-virtualized`.
- `disabled`: If this is set to `true`, then all of the downshift item event
  handlers will be omitted. Items will not be highlighted when hovered, and
  items will not be selected when clicked.

#### `getToggleButtonProps`

Call this and apply the returned props to a `button`. It allows you to toggle
the `Menu` component. You can definitely build something like this yourself (all
of the available APIs are exposed to you), but this is nice because it will also
apply all of the proper ARIA attributes.

Optional properties:

- `disabled`: If this is set to `true`, then all of the downshift button event
  handlers will be omitted (it wont toggle the menu when clicked).
- `aria-label`: The `aria-label` prop is in English. You should probably
  override this yourself so you can provide translations:

```jsx
const myButton = (
  <button
    {...getToggleButtonProps({
      'aria-label': translateWithId(isOpen ? 'close.menu' : 'open.menu'),
    })}
  />
)
```

### actions

These are functions you can call to change the state of the downshift component.



| property                | type                                                             | description                                                                                                                                                                                                                                                            |
| ----------------------- | ---------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `clearSelection`        | `function(cb: Function)`                                         | clears the selection                                                                                                                                                                                                                                                   |
| `clearItems`            | `function()`                                                     | Clears downshift's record of all the items. Only really useful if you render your items asynchronously within downshift. See [#186](https://github.com/downshift-js/downshift/issues/186)                                                                              |
| `closeMenu`             | `function(cb: Function)`                                         | closes the menu                                                                                                                                                                                                                                                        |
| `openMenu`              | `function(cb: Function)`                                         | opens the menu                                                                                                                                                                                                                                                         |
| `selectHighlightedItem` | `function(otherStateToSet: object, cb: Function)`                | selects the item that is currently highlighted                                                                                                                                                                                                                         |
| `selectItem`            | `function(item: any, otherStateToSet: object, cb: Function)`     | selects the given item                                                                                                                                                                                                                                                 |
| `selectItemAtIndex`     | `function(index: number, otherStateToSet: object, cb: Function)` | selects the item at the given index                                                                                                                                                                                                                                    |
| `setHighlightedIndex`   | `function(index: number, otherStateToSet: object, cb: Function)` | call to set a new highlighted index                                                                                                                                                                                                                                    |
| `toggleMenu`            | `function(otherStateToSet: object, cb: Function)`                | toggle the menu open state                                                                                                                                                                                                                                             |
| `reset`                 | `function(otherStateToSet: object, cb: Function)`                | this resets downshift's state to a reasonable default                                                                                                                                                                                                                  |
| `setItemCount`          | `function(count: number)`                                        | this sets the `itemCount`. Handy in situations where you're using windowing and the items are loaded asynchronously from within downshift (so you can't use the `itemCount` prop.                                                                                      |
| `unsetItemCount`        | `function()`                                                     | this unsets the `itemCount` which means the item count will be calculated instead by the `itemCount` prop or based on how many times you call `getItemProps`.                                                                                                          |
| `setState`              | `function(stateToSet: object, cb: Function)`                     | This is a general `setState` function. It uses downshift's `internalSetState` function which works with control props and calls your `onSelect`, `onChange`, etc. (Note, you can specify a `type` which you can reference in some other APIs like the `stateReducer`). |

> `otherStateToSet` refers to an object to set other internal state. It is
> recommended to avoid abusing this, but is available if you need it.

### state

These are values that represent the current state of the downshift component.



| property           | type              | description                                    |
| ------------------ | ----------------- | ---------------------------------------------- |
| `highlightedIndex` | `number` / `null` | the currently highlighted item                 |
| `inputValue`       | `string` / `null` | the current value of the `getInputProps` input |
| `isOpen`           | `boolean`         | the menu open state                            |
| `selectedItem`     | `any`             | the currently selected item input              |

### props

As a convenience, the `id` and `itemToString` props which you pass to
`<Downshift />` are available here as well.

## Event Handlers

Downshift has a few events for which it provides implicit handlers. Several of
these handlers call `event.preventDefault()`. Their additional functionality is
described below.

### default handlers

- `ArrowDown`: if menu is closed, opens it and moves the highlighted index to
  `defaultHighlightedIndex + 1`, if `defaultHighlightedIndex` is provided, or to
  the top-most item, if not. If menu is open, it moves the highlighted index
  down by 1. If the shift key is held when this event fires, the highlighted
  index will jump down 5 indices instead of 1. NOTE: if the current highlighted
  index is within the bottom 5 indices, the top-most index will be highlighted.)

- `ArrowUp`: if menu is closed, opens it and moves the highlighted index to
  `defaultHighlightedIndex - 1`, if `defaultHighlightedIndex` is provided, or to
  the bottom-most item, if not. If menu is open, moves the highlighted index up
  by 1. If the shift key is held when this event fires, the highlighted index
  will jump up 5 indices instead of 1. NOTE: if the current highlighted index is
  within the top 5 indices, the bottom-most index will be highlighted.)

- `Home`: if menu is closed, it will not add any other behavior. If menu is
  open, the top-most index will get highlighted.

- `End`: if menu is closed, it will not add any other behavior. If menu is open,
  the bottom-most index will get highlighted.

- `Enter`: if the menu is open, selects the currently highlighted item. If the
  menu is open, the usual 'Enter' event is prevented by Downshift's default
  implicit enter handler; so, for example, a form submission event will not work
  as one might expect (though if the menu is closed the form submission will
  work normally). See below for customizing the handlers.

- `Escape`: will clear downshift's state. This means that `highlightedIndex`
  will be set to the `defaultHighlightedIndex` and the `isOpen` state will be
  set to the `defaultIsOpen`. If `isOpen` is already false, the `inputValue`
  will be set to an empty string and `selectedItem` will be set to `null`

### customizing handlers

You can provide your own event handlers to Downshift which will be called before
the default handlers:

```javascript
const ui = (
  <Downshift>
    {({getInputProps}) => (
      <input
        {...getInputProps({
          onKeyDown: event => {
            // your handler code
          },
        })}
      />
    )}
  </Downshift>
)
```

If you would like to prevent the default handler behavior in some cases, you can
set the event's `preventDownshiftDefault` property to `true`:

```javascript
const ui = (
  <Downshift>
    {({getInputProps}) => (
      <input
        {...getInputProps({
          onKeyDown: event => {
            if (event.key === 'Enter') {
              // Prevent Downshift's default 'Enter' behavior.
              event.nativeEvent.preventDownshiftDefault = true

              // your handler code
            }
          },
        })}
      />
    )}
  </Downshift>
)
```

If you would like to completely override Downshift's behavior for a handler, in
favor of your own, you can bypass prop getters:

```javascript
const ui = (
  <Downshift>
    {({getInputProps}) => (
      <input
        {...getInputProps()}
        onKeyDown={event => {
          // your handler code
        }}
      />
    )}
  </Downshift>
)
```

## Utilities

### resetIdCounter

Allows reseting the internal id counter which is used to generate unique ids for
Downshift component.

**This is unnecessary if you are using React 18 or newer**

You should never need to use this in the browser. Only if you are running an
universal React app that is rendered on the server you should call
[resetIdCounter](#resetidcounter) before every render so that the ids that get
generated on the server match the ids generated in the browser.

```javascript
import {resetIdCounter} from 'downshift';

resetIdCounter()
ReactDOMServer.renderToString(...);
```

## React Native

Since Downshift renders it's UI using render props, Downshift supports rendering
on React Native with ease. Use components like `<View>`, `<Text>`,
`<TouchableOpacity>` and others inside of your render method to generate awesome
autocomplete, dropdown, or selection components.

### Gotchas

- Your root view will need to either pass a ref to `getRootProps` or call
  `getRootProps` with `{ suppressRefError: true }`. This ref is used to catch a
  common set of errors around composite components.
  [Learn more in `getRootProps`](#getrootprops).
- When using a `<FlatList>` or `<ScrollView>`, be sure to supply the
  [`keyboardShouldPersistTaps`](https://facebook.github.io/react-native/docs/scrollview.html#keyboardshouldpersisttaps)
  prop to ensure that your text input stays focus, while allowing for taps on
  the touchables rendered for your items.

## Advanced React Component Patterns course

[Kent C. Dodds](https://twitter.com/kentcdodds) has created learning material
based on the patterns implemented in this component. You can find it on various
platforms:

1.  [egghead.io](https://egghead.io/courses/advanced-react-component-patterns)
2.  [Frontend Masters](https://frontendmasters.com/courses/advanced-react-patterns/)
3.  YouTube (for free!):
    [Part 1](https://www.youtube.com/watch?v=SuzutbwjUp8&list=PLV5CVI1eNcJgNqzNwcs4UKrlJdhfDjshf)
    and
    [Part 2](https://www.youtube.com/watch?v=ubXtOROjILU&list=PLV5CVI1eNcJgNqzNwcs4UKrlJdhfDjshf)

## Examples

> 🚨 We're in the process of moving all examples to the
> [downshift-examples](https://github.com/downshift-js/downshift-examples) repo
> (which you can open, interact with, and contribute back to live on
> [codesandbox](https://codesandbox.io/p/sandbox/github/kentcdodds/downshift-examples?file=%2Fsrc%2Findex.js&moduleview=1))

> 🚨 We're also in the process of updating our examples from the
> [downshift-docs](https://github.com/downshift-js/downshift-docs) repo which is
> actually used to create our docsite at [downshift-js.com][docsite]). Make sure
> to check it out for the most relevant Downshift examples or try out the new
> hooks that aim to replace Downshift.

**Ordered Examples:**

If you're just learning downshift, review these in order:

0.  [basic automplete with getRootProps](https://codesandbox.io/p/sandbox/github/kentcdodds/downshift-examples?file=%2Fsrc%2Fdownshift%2Fordered-examples%2F00-get-root-props-example.js%3A11%2C21&moduleview=1) -
    the same as example #1 but using the correct HTML structure as suggested by
    ARIA-WCAG.
1.  [basic autocomplete](https://codesandbox.io/p/sandbox/github/kentcdodds/downshift-examples?file=%2Fsrc%2Fdownshift%2Fordered-examples%2F01-basic-autocomplete.js&moduleview=1) -
    very bare bones, not styled at all. Good place to start.
2.  [styled autocomplete](https://codesandbox.io/p/sandbox/github/kentcdodds/downshift-examples?file=%2Fsrc%2Fdownshift%2Fordered-examples%2F02-complete-autocomplete.js&moduleview=1) -
    more complete autocomplete solution using emotion for styling and
    match-sorter for filtering the items.
3.  [typeahead](https://codesandbox.io/p/sandbox/github/kentcdodds/downshift-examples?file=%2Fsrc%2Fdownshift%2Fordered-examples%2F03-typeahead.js&moduleview=1) -
    Shows how to control the `selectedItem` so the selected item can be one of
    your items or whatever the user types.
4.  [multi-select](https://codesandbox.io/p/sandbox/github/kentcdodds/downshift-examples?file=%2Fsrc%2Fdownshift%2Fordered-examples%2F04-multi-select.js&moduleview=1) -
    Shows how to create a MultiDownshift component that allows for an array of
    selectedItems for multiple selection using a state reducer

**Other Examples:**

Check out these examples of more advanced use/edge cases:

- [dropdown with select by key](https://codesandbox.io/p/sandbox/github/kentcdodds/downshift-examples?file=%2Fsrc%2Fdownshift%2Fother-examples%2Fdropdown-select-by-key%2FCustomDropdown%2Findex.js&moduleview=1) -
  An example of using the render prop pattern to utilize a reusable component to
  provide the downshift dropdown component with the functionality of being able
  to highlight a selection item that starts with the key pressed.
- [using actions](https://codesandbox.io/p/sandbox/github/kentcdodds/downshift-examples?file=%2Fsrc%2Fdownshift%2Fother-examples%2Fusing-actions.js&moduleview=1) -
  An example of using one of downshift's actions as an event handler.
- [gmail's composition recipients field](https://codesandbox.io/p/sandbox/github/kentcdodds/downshift-examples?file=%2Fsrc%2Fdownshift%2Fother-examples%2Fgmail%2Findex.js&moduleview=1) -
  An example of a highly complex autocomplete component featuring asynchronously
  loading items, multiple selection, and windowing (with react-virtualized)
- [Downshift HOC and Compound Components](https://codesandbox.io/p/sandbox/github/kentcdodds/downshift-examples?file=%2Fsrc%2Fdownshift%2Fother-examples%2Fhoc%2Findex.js&moduleview=1) -
  An example of how to implementat compound components with
  `React.createContext` and a downshift higher order component. This is
  generally not recommended because the render prop API exported by downshift is
  generally good enough for everyone, but there's nothing technically wrong with
  doing something like this.

**Old Examples exist on [codesandbox.io][examples]:**

_🚨 This is a great contribution opportunity!_ These are examples that have not
yet been migrated to
[downshift-examples](https://codesandbox.io/p/sandbox/github/kentcdodds/downshift-examples?file=%2Fsrc%2Findex.js&moduleview=1).
You're more than welcome to make PRs to the examples repository to move these
examples over there.
[Watch this to learn how to contribute completely in the browser](https://www.youtube.com/watch?v=3PAQbhdkTtI&index=2&t=21s&list=PLV5CVI1eNcJgCrPH_e6d57KRUTiDZgs0u)

- [Integration with Apollo](https://codesandbox.io/s/m5zrvqj85p)
- [Integration with Redux](https://codesandbox.io/s/3ywmnyr0zq)
- [Integration with `react-instantsearch`](https://codesandbox.io/s/kvn0lpp83)
  from Algolia
- [Material-UI (1.0.0-beta.4) Combobox Using Downshift](https://codesandbox.io/s/QMGq4kAY)
- [Material-UI (1.0.0-beta.33) Multiple select with autocomplete](https://codesandbox.io/s/7k3674z09q)
- [Integration with `GenieJS`](https://codesandbox.io/s/jRLKrxwgl)
  ([learn more about `genie` here](https://github.com/kentcdodds/genie))
- [Handling and displaying errors](https://codesandbox.io/s/zKE37vorr)
- [Integration with React Router](https://codesandbox.io/s/ww9lwloy8w)
- [Windowing with `react-tiny-virtual-list`](https://codesandbox.io/s/v670kq95l)
- [Section/option group example](https://codesandbox.io/s/zx1kj58npl)
- [Integration with `fuzzaldrin-plus` (Fuzzy matching)](https://codesandbox.io/s/pyq3v4o3j)
- [Dropdown/select implementation with Bootstrap](https://codesandbox.io/s/53y8jvpj0k)
- [Multiple editable tag selection](https://codesandbox.io/s/o4yp9vmm8z)
- [Downshift implemented as compound components and a Higher Order Component](https://codesandbox.io/s/017n1jqo00)
  (exposes a `withDownshift` higher order component which you can use to get at
  the state, actions, prop getters in a rendered downshift tree).
- [Downshift Spectre.css example](https://codesandbox.io/s/M89KQOBRB)
- [Integration with `redux-form`](https://codesandbox.io/s/k594964z13)
- [Integration with `react-final-form`](https://codesandbox.io/s/qzm43nn2mj)
- [Provider Pattern](https://codesandbox.io/s/mywzk3133p) - how to avoid
  prop-drilling if you like to break up your render method into more components
- [React Native example](https://snack.expo.io/SkE0LxXqM)
- [React VR example](https://github.com/infiniteluke/bassdrop)
- [Multiple checkbox selection](https://codesandbox.io/s/5z711pmr3l)

## FAQ

<details>

<summary>
  How do I avoid the checksum error when server rendering (SSR)?
</summary>

The checksum error you're seeing is most likely due to the automatically
generated `id` and/or `htmlFor` prop you get from `getInputProps` and
`getLabelProps` (respectively). It could also be from the automatically
generated `id` prop you get from `getItemProps` (though this is not likely as
you're probably not rendering any items when rendering a downshift component on
the server).

To avoid these problems, simply call [resetIdCounter](#resetidcounter) before
`ReactDOM.renderToString`.

Alternatively you could provide your own ids via the id props where you render
`<Downshift />`:

```javascript
const ui = (
  <Downshift
    id="autocomplete"
    labelId="autocomplete-label"
    inputId="autocomplete-input"
    menuId="autocomplete-menu"
  >
    {({getInputProps, getLabelProps}) => <div>{/* your UI */}</div>}
  </Downshift>
)
```

</details>

## Inspiration

I was heavily inspired by [Ryan Florence][ryan]. Watch his (free) lesson about
["Compound Components"][compound-components-lecture]. Initially downshift was a
group of compound components using context to communicate. But then [Jared
Forsyth][jared] suggested I expose functions (the prop getters) to get props to
apply to the elements rendered. That bit of inspiration made a big impact on the
flexibility and simplicity of this API.

I also took a few ideas from the code in
[`react-autocomplete`][react-autocomplete] and [jQuery UI's
Autocomplete][jquery-complete].

You can watch me build the first iteration of `downshift` on YouTube:

- [Part 1](https://www.youtube.com/watch?v=2kzD1IjDy5s&list=PLV5CVI1eNcJh5CTgArGVwANebCrAh2OUE&index=11)
- [Part 2](https://www.youtube.com/watch?v=w1Z7Jvj08_s&list=PLV5CVI1eNcJh5CTgArGVwANebCrAh2OUE&index=10)

You'll find more recordings of me working on `downshift` on [my livestream
YouTube playlist][yt-playlist].

## Other Solutions

You can implement these other solutions using `downshift`, but if you'd prefer
to use these out of the box solutions, then that's fine too:

- [`react-select`](https://github.com/JedWatson/react-select)
- [`react-autosuggest`](https://github.com/moroshko/react-autosuggest)

## Bindings for ReasonML

If you're developing some React in ReasonML, check out the
[`Downshift` bindings](https://github.com/reasonml-community/bs-downshift) for
that.

## Contributors

Thanks goes to these people ([emoji key][emojis]):




<table>
  <tbody>
    <tr>
      <td align="center" valign="top" width="14.28%"><a href="https://kentcdodds.com"><img src="https://avatars.githubusercontent.com/u/1500684?v=3?s=100" width="100px;" alt="Kent C. Dodds"/><br /><sub><b>Kent C. Dodds</b></sub></a><br /><a href="https://github.com/downshift-js/downshift/commits?author=kentcdodds" title="Code">💻</a> <a href="https://github.com/downshift-js/downshift/commits?author=kentcdodds" title="Documentation">📖</a> <a href="#infra-kentcdodds" title="Infrastructure (Hosting, Build-Tools, etc)">🚇</a> <a href="https://github.com/downshift-js/downshift/commits?author=kentcdodds" title="Tests">⚠️</a> <a href="https://github.com/downshift-js/downshift/pulls?q=is%3Apr+reviewed-by%3Akentcdodds" title="Reviewed Pull Requests">👀</a> <a href="#blog-kentcdodds" title="Blogposts">📝</a> <a href="https://github.com/downshift-js/downshift/issues?q=author%3Akentcdodds" title="Bug reports">🐛</a> <a href="#example-kentcdodds" title="Examples">💡</a> <a href="#ideas-kentcdodds" title="Ideas, Planning, & Feedback">🤔</a> <a href="#talk-kentcdodds" title="Talks">📢</a></td>
      <td align="center" valign="top" width="14.28%"><a href="http://twitter.com/ryanflorence"><img src="https://avatars0.githubusercontent.com/u/100200?v=4?s=100" width="100px;" alt="Ryan Florence"/><br /><sub><b>Ryan Florence</b></sub></a><br /><a href="#ideas-ryanflorence" title="Ideas, Planning, & Feedback">🤔</a></td>
      <td align="center" valign="top" width="14.28%"><a href="http://jaredforsyth.com"><img src="https://avatars3.githubusercontent.com/u/112170?v=4?s=100" width="100px;" alt="Jared Forsyth"/><br /><sub><b>Jared Forsyth</b></sub></a><br /><a href="#ideas-jaredly" title="Ideas, Planning, & Feedback">🤔</a> <a href="https://github.com/downshift-js/downshift/commits?author=jaredly" title="Documentation">📖</a></td>
      <td align="center" valign="top" width="14.28%"><a href="https://github.com/jtmthf"><img src="https://avatars1.githubusercontent.com/u/8162598?v=4?s=100" width="100px;" alt="Jack Moore"/><br /><sub><b>Jack Moore</b></sub></a><br /><a href="#example-jtmthf" title="Examples">💡</a></td>
      <td align="center" valign="top" width="14.28%"><a href="https://souporserious.com/"><img src="https://avatars1.githubusercontent.com/u/2762082?v=4?s=100" width="100px;" alt="Travis Arnold"/><br /><sub><b>Travis Arnold</b></sub></a><br /><a href="https://github.com/downshift-js/downshift/commits?author=souporserious" title="Code">💻</a> <a href="https://github.com/downshift-js/downshift/commits?author=souporserious" title="Documentation">📖</a></td>
      <td align="center" valign="top" width="14.28%"><a href="http://marcysutton.com"><img src="https://avatars0.githubusercontent.com/u/1045233?v=4?s=100" width="100px;" alt="Marcy Sutton"/><br /><sub><b>Marcy Sutton</b></sub></a><br /><a href="https://github.com/downshift-js/downshift/issues?q=author%3Amarcysutton" title="Bug reports">🐛</a> <a href="#ideas-marcysutton" title="Ideas, Planning, & Feedback">🤔</a></td>
      <td align="center" valign="top" width="14.28%"><a href="http://www.jeremygayed.com"><img src="https://avatars2.githubusercontent.com/u/244704?v=4?s=100" width="100px;" alt="Jeremy Gayed"/><br /><sub><b>Jeremy Gayed</b></sub></a><br /><a href="#example-tizmagik" title="Examples">💡</a></td>
    </tr>
    <tr>
      <td align="center" valign="top" width="14.28%"><a href="https://haroen.me"><img src="https://avatars3.githubusercontent.com/u/6270048?v=4?s=100" width="100px;" alt="Haroen Viaene"/><br /><sub><b>Haroen Viaene</b></sub></a><br /><a href="#example-Haroenv" title="Examples">💡</a></td>
      <td align="center" valign="top" width="14.28%"><a href="https://github.com/rezof"><img src="https://avatars2.githubusercontent.com/u/15073300?v=4?s=100" width="100px;" alt="monssef"/><br /><sub><b>monssef</b></sub></a><br /><a href="#example-rezof" title="Examples">💡</a></td>
      <td align="center" valign="top" width="14.28%"><a href="https://fezvrasta.github.io"><img src="https://avatars2.githubusercontent.com/u/5382443?v=4?s=100" width="100px;" alt="Federico Zivolo"/><br /><sub><b>Federico Zivolo</b></sub></a><br /><a href="https://github.com/downshift-js/downshift/commits?author=FezVrasta" title="Documentation">📖</a></td>
      <td align="center" valign="top" width="14.28%"><a href="https://divyendusingh.com"><img src="https://avatars3.githubusercontent.com/u/746482?v=4?s=100" width="100px;" alt="Divyendu Singh"/><br /><sub><b>Divyendu Singh</b></sub></a><br /><a href="#example-divyenduz" title="Examples">💡</a> <a href="https://github.com/downshift-js/downshift/commits?author=divyenduz" title="Code">💻</a> <a href="https://github.com/downshift-js/downshift/commits?author=divyenduz" title="Documentation">📖</a> <a href="https://github.com/downshift-js/downshift/commits?author=divyenduz" title="Tests">⚠️</a></td>
      <td align="center" valign="top" width="14.28%"><a href="https://github.com/salmanmanekia"><img src="https://avatars1.githubusercontent.com/u/841955?v=4?s=100" width="100px;" alt="Muhammad Salman"/><br /><sub><b>Muhammad Salman</b></sub></a><br /><a href="https://github.com/downshift-js/downshift/commits?author=salmanmanekia" title="Code">💻</a></td>
      <td align="center" valign="top" width="14.28%"><a href="https://twitter.com/psicotropidev"><img src="https://avatars3.githubusercontent.com/u/10820159?v=4?s=100" width="100px;" alt="João Alberto"/><br /><sub><b>João Alberto</b></sub></a><br /><a href="https://github.com/downshift-js/downshift/commits?author=psicotropicos" title="Code">💻</a></td>
      <td align="center" valign="top" width="14.28%"><a href="https://github.com/bernard-lin"><img src="https://avatars0.githubusercontent.com/u/16327281?v=4?s=100" width="100px;" alt="Bernard Lin"/><br /><sub><b>Bernard Lin</b></sub></a><br /><a href="https://github.com/downshift-js/downshift/commits?author=bernard-lin" title="Code">💻</a> <a href="https://github.com/downshift-js/downshift/commits?author=bernard-lin" title="Documentation">📖</a></td>
    </tr>
    <tr>
      <td align="center" valign="top" width="14.28%"><a href="https://geoffdavis.info"><img src="https://avatars1.githubusercontent.com/u/7330124?v=4?s=100" width="100px;" alt="Geoff Davis"/><br /><sub><b>Geoff Davis</b></sub></a><br /><a href="#example-geoffdavis92" title="Examples">💡</a></td>
      <td align="center" valign="top" width="14.28%"><a href="https://github.com/reznord"><img src="https://avatars0.githubusercontent.com/u/3415488?v=4?s=100" width="100px;" alt="Anup"/><br /><sub><b>Anup</b></sub></a><br /><a href="https://github.com/downshift-js/downshift/commits?author=reznord" title="Documentation">📖</a></td>
      <td align="center" valign="top" width="14.28%"><a href="http://ferdinandsalis.com"><img src="https://avatars0.githubusercontent.com/u/340520?v=4?s=100" width="100px;" alt="Ferdinand Salis"/><br /><sub><b>Ferdinand Salis</b></sub></a><br /><a href="https://github.com/downshift-js/downshift/issues?q=author%3Aferdinandsalis" title="Bug reports">🐛</a> <a href="https://github.com/downshift-js/downshift/commits?author=ferdinandsalis" title="Code">💻</a></td>
      <td align="center" valign="top" width="14.28%"><a href="https://github.com/tkh44"><img src="https://avatars2.githubusercontent.com/u/662750?v=4?s=100" width="100px;" alt="Kye Hohenberger"/><br /><sub><b>Kye Hohenberger</b></sub></a><br /><a href="https://github.com/downshift-js/downshift/issues?q=author%3Atkh44" title="Bug reports">🐛</a></td>
      <td align="center" valign="top" width="14.28%"><a href="https://github.com/jgoux"><img src="https://avatars0.githubusercontent.com/u/1443499?v=4?s=100" width="100px;" alt="Julien Goux"/><br /><sub><b>Julien Goux</b></sub></a><br /><a href="https://github.com/downshift-js/downshift/issues?q=author%3Ajgoux" title="Bug reports">🐛</a> <a href="https://github.com/downshift-js/downshift/commits?author=jgoux" title="Code">💻</a> <a href="https://github.com/downshift-js/downshift/commits?author=jgoux" title="Tests">⚠️</a></td>
      <td align="center" valign="top" width="14.28%"><a href="https://github.com/jseminck"><img src="https://avatars2.githubusercontent.com/u/9586897?v=4?s=100" width="100px;" alt="Joachim Seminck"/><br /><sub><b>Joachim Seminck</b></sub></a><br /><a href="https://github.com/downshift-js/downshift/commits?author=jseminck" title="Code">💻</a></td>
      <td align="center" valign="top" width="14.28%"><a href="http://jesseharlin.net/"><img src="https://avatars3.githubusercontent.com/u/954596?v=4?s=100" width="100px;" alt="Jesse Harlin"/><br /><sub><b>Jesse Harlin</b></sub></a><br /><a href="https://github.com/downshift-js/downshift/issues?q=author%3Athe-simian" title="Bug reports">🐛</a> <a href="#example-the-simian" title="Examples">💡</a></td>
    </tr>
    <tr>
      <td align="center" valign="top" width="14.28%"><a href="https://github.com/pbomb"><img src="https://avatars0.githubusercontent.com/u/1402095?v=4?s=100" width="100px;" alt="Matt Parrish"/><br /><sub><b>Matt Parrish</b></sub></a><br /><a href="#tool-pbomb" title="Tools">🔧</a> <a href="https://github.com/downshift-js/downshift/pulls?q=is%3Apr+reviewed-by%3Apbomb" title="Reviewed Pull Requests">👀</a></td>
      <td align="center" valign="top" width="14.28%"><a href="http://thom.kr"><img src="https://avatars1.githubusercontent.com/u/11661846?v=4?s=100" width="100px;" alt="thom"/><br /><sub><b>thom</b></sub></a><br /><a href="https://github.com/downshift-js/downshift/commits?author=thomhos" title="Code">💻</a></td>
      <td align="center" valign="top" width="14.28%"><a href="http://twitter.com/tranvu"><img src="https://avatars2.githubusercontent.com/u/1088312?v=4?s=100" width="100px;" alt="Vu Tran"/><br /><sub><b>Vu Tran</b></sub></a><br /><a href="https://github.com/downshift-js/downshift/commits?author=vutran" title="Code">💻</a></td>
      <td align="center" valign="top" width="14.28%"><a href="https://github.com/codiemullins"><img src="https://avatars1.githubusercontent.com/u/74193?v=4?s=100" width="100px;" alt="Codie Mullins"/><br /><sub><b>Codie Mullins</b></sub></a><br /><a href="https://github.com/downshift-js/downshift/commits?author=codiemullins" title="Code">💻</a> <a href="#example-codiemullins" title="Examples">💡</a></td>
      <td align="center" valign="top" width="14.28%"><a href="https://morajabi.me"><img src="https://avatars3.githubusercontent.com/u/12202757?v=4?s=100" width="100px;" alt="Mohammad Rajabifard"/><br /><sub><b>Mohammad Rajabifard</b></sub></a><br /><a href="https://github.com/downshift-js/downshift/commits?author=morajabi" title="Documentation">📖</a> <a href="#ideas-morajabi" title="Ideas, Planning, & Feedback">🤔</a></td>
      <td align="center" valign="top" width="14.28%"><a href="https://github.com/tansongyang"><img src="https://avatars3.githubusercontent.com/u/9488719?v=4?s=100" width="100px;" alt="Frank Tan"/><br /><sub><b>Frank Tan</b></sub></a><br /><a href="https://github.com/downshift-js/downshift/commits?author=tansongyang" title="Code">💻</a></td>
      <td align="center" valign="top" width="14.28%"><a href="https://kierb.com"><img src="https://avatars3.githubusercontent.com/u/5093058?v=4?s=100" width="100px;" alt="Kier Borromeo"/><br /><sub><b>Kier Borromeo</b></sub></a><br /><a href="#example-srph" title="Examples">💡</a></td>
    </tr>
    <tr>
      <td align="center" valign="top" width="14.28%"><a href="https://github.com/paul-veevers"><img src="https://avatars1.githubusercontent.com/u/8969456?v=4?s=100" width="100px;" alt="Paul Veevers"/><br /><sub><b>Paul Veevers</b></sub></a><br /><a href="https://github.com/downshift-js/downshift/commits?author=paul-veevers" title="Code">💻</a></td>
      <td align="center" valign="top" width="14.28%"><a href="https://github.com/Ronolibert"><img src="https://avatars2.githubusercontent.com/u/13622298?v=4?s=100" width="100px;" alt="Ron Cruz"/><br /><sub><b>Ron Cruz</b></sub></a><br /><a href="https://github.com/downshift-js/downshift/commits?author=Ronolibert" title="Documentation">📖</a></td>
      <td align="center" valign="top" width="14.28%"><a href="http://rickmcgavin.github.io"><img src="https://avatars1.githubusercontent.com/u/13605633?v=4?s=100" width="100px;" alt="Rick McGavin"/><br /><sub><b>Rick McGavin</b></sub></a><br /><a href="https://github.com/downshift-js/downshift/commits?author=rickMcGavin" title="Documentation">📖</a></td>
      <td align="center" valign="top" width="14.28%"><a href="http://twitter.com/vejersele"><img src="https://avatars0.githubusercontent.com/u/869669?v=4?s=100" width="100px;" alt="Jelle Versele"/><br /><sub><b>Jelle Versele</b></sub></a><br /><a href="#example-vejersele" title="Examples">💡</a></td>
      <td align="center" valign="top" width="14.28%"><a href="https://github.com/brentertz"><img src="https://avatars1.githubusercontent.com/u/202773?v=4?s=100" width="100px;" alt="Brent Ertz"/><br /><sub><b>Brent Ertz</b></sub></a><br /><a href="#ideas-brentertz" title="Ideas, Planning, & Feedback">🤔</a></td>
      <td align="center" valign="top" width="14.28%"><a href="https://github.com/Dajust"><img src="https://avatars3.githubusercontent.com/u/8015514?v=4?s=100" width="100px;" alt="Justice Mba "/><br /><sub><b>Justice Mba </b></sub></a><br /><a href="https://github.com/downshift-js/downshift/commits?author=Dajust" title="Code">💻</a> <a href="https://github.com/downshift-js/downshift/commits?author=Dajust" title="Documentation">📖</a> <a href="#ideas-Dajust" title="Ideas, Planning, & Feedback">🤔</a></td>
      <td align="center" valign="top" width="14.28%"><a href="http://mfellis.com"><img src="https://avatars2.githubusercontent.com/u/3925281?v=4?s=100" width="100px;" alt="Mark Ellis"/><br /><sub><b>Mark Ellis</b></sub></a><br /><a href="#ideas-ellismarkf" title="Ideas, Planning, & Feedback">🤔</a></td>
    </tr>
    <tr>
      <td align="center" valign="top" width="14.28%"><a href="http://ronak.io/"><img src="https://avatars1.githubusercontent.com/u/3241922?v=4?s=100" width="100px;" alt="us͡an̸df͘rien͜ds͠"/><br /><sub><b>us͡an̸df͘rien͜ds͠</b></sub></a><br /><a href="https://github.com/downshift-js/downshift/issues?q=author%3Ausandfriends" title="Bug reports">🐛</a> <a href="https://github.com/downshift-js/downshift/commits?author=usandfriends" title="Code">💻</a> <a href="https://github.com/downshift-js/downshift/commits?author=usandfriends" title="Tests">⚠️</a></td>
      <td align="center" valign="top" width="14.28%"><a href="https://www.robin-drexler.com/"><img src="https://avatars0.githubusercontent.com/u/474248?v=4?s=100" width="100px;" alt="Robin Drexler"/><br /><sub><b>Robin Drexler</b></sub></a><br /><a href="https://github.com/downshift-js/downshift/issues?q=author%3Arobin-drexler" title="Bug reports">🐛</a> <a href="https://github.com/downshift-js/downshift/commits?author=robin-drexler" title="Code">💻</a></td>
      <td align="center" valign="top" width="14.28%"><a href="http://arturoromero.info/"><img src="https://avatars0.githubusercontent.com/u/7406639?v=4?s=100" width="100px;" alt="Arturo Romero"/><br /><sub><b>Arturo Romero</b></sub></a><br /><a href="#example-arturoromeroslc" title="Examples">💡</a></td>
      <td align="center" valign="top" width="14.28%"><a href="http://algolab.eu/pirola"><img src="https://avatars1.githubusercontent.com/u/275483?v=4?s=100" width="100px;" alt="yp"/><br /><sub><b>yp</b></sub></a><br /><a href="https://github.com/downshift-js/downshift/issues?q=author%3Ayp" title="Bug reports">🐛</a> <a href="https://github.com/downshift-js/downshift/commits?author=yp" title="Code">💻</a> <a href="https://github.com/downshift-js/downshift/commits?author=yp" title="Tests">⚠️</a></td>
      <td align="center" valign="top" width="14.28%"><a href="http://www.warbyparker.com"><img src="https://avatars0.githubusercontent.com/u/3998604?v=4?s=100" width="100px;" alt="Dave Garwacke"/><br /><sub><b>Dave Garwacke</b></sub></a><br /><a href="https://github.com/downshift-js/downshift/commits?author=ifyoumakeit" title="Documentation">📖</a></td>
      <td align="center" valign="top" width="14.28%"><a href="http://linkedin.com/in/drapegnik"><img src="https://avatars3.githubusercontent.com/u/11758660?v=4?s=100" width="100px;" alt="Ivan Pazhitnykh"/><br /><sub><b>Ivan Pazhitnykh</b></sub></a><br /><a href="https://github.com/downshift-js/downshift/commits?author=Drapegnik" title="Code">💻</a> <a href="https://github.com/downshift-js/downshift/commits?author=Drapegnik" title="Tests">⚠️</a></td>
      <td align="center" valign="top" width="14.28%"><a href="https://github.com/Rendez"><img src="https://avatars0.githubusercontent.com/u/61776?v=4?s=100" width="100px;" alt="Luis Merino"/><br /><sub><b>Luis Merino</b></sub></a><br /><a href="https://github.com/downshift-js/downshift/commits?author=Rendez" title="Documentation">📖</a></td>
    </tr>
    <tr>
      <td align="center" valign="top" width="14.28%"><a href="http://twitter.com/arahansen"><img src="https://avatars0.githubusercontent.com/u/8746094?v=4?s=100" width="100px;" alt="Andrew Hansen"/><br /><sub><b>Andrew Hansen</b></sub></a><br /><a href="https://github.com/downshift-js/downshift/commits?author=arahansen" title="Code">💻</a> <a href="https://github.com/downshift-js/downshift/commits?author=arahansen" title="Tests">⚠️</a> <a href="#ideas-arahansen" title="Ideas, Planning, & Feedback">🤔</a></td>
      <td align="center" valign="top" width="14.28%"><a href="http://www.johnwhiles.com"><img src="https://avatars3.githubusercontent.com/u/20307225?v=4?s=100" width="100px;" alt="John Whiles"/><br /><sub><b>John Whiles</b></sub></a><br /><a href="https://github.com/downshift-js/downshift/commits?author=Jwhiles" title="Code">💻</a></td>
      <td align="center" valign="top" width="14.28%"><a href="https://github.com/wKovacs64"><img src="https://avatars1.githubusercontent.com/u/1288694?v=4?s=100" width="100px;" alt="Justin Hall"/><br /><sub><b>Justin Hall</b></sub></a><br /><a href="#infra-wKovacs64" title="Infrastructure (Hosting, Build-Tools, etc)">🚇</a></td>
      <td align="center" valign="top" width="14.28%"><a href="https://twitter.com/pete_tnt"><img src="https://avatars2.githubusercontent.com/u/7641760?v=4?s=100" width="100px;" alt="Pete Nykänen"/><br /><sub><b>Pete Nykänen</b></sub></a><br /><a href="https://github.com/downshift-js/downshift/pulls?q=is%3Apr+reviewed-by%3Apetetnt" title="Reviewed Pull Requests">👀</a></td>
      <td align="center" valign="top" width="14.28%"><a href="http://jaredpalmer.com"><img src="https://avatars2.githubusercontent.com/u/4060187?v=4?s=100" width="100px;" alt="Jared Palmer"/><br /><sub><b>Jared Palmer</b></sub></a><br /><a href="https://github.com/downshift-js/downshift/commits?author=jaredpalmer" title="Code">💻</a></td>
      <td align="center" valign="top" width="14.28%"><a href="http://www.philipyoungg.com"><img src="https://avatars3.githubusercontent.com/u/11477718?v=4?s=100" width="100px;" alt="Philip Young"/><br /><sub><b>Philip Young</b></sub></a><br /><a href="https://github.com/downshift-js/downshift/commits?author=philipyoungg" title="Code">💻</a> <a href="https://github.com/downshift-js/downshift/commits?author=philipyoungg" title="Tests">⚠️</a> <a href="#ideas-philipyoungg" title="Ideas, Planning, & Feedback">🤔</a></td>
      <td align="center" valign="top" width="14.28%"><a href="https://alexandernanberg.com"><img src="https://avatars3.githubusercontent.com/u/8997319?v=4?s=100" width="100px;" alt="Alexander Nanberg"/><br /><sub><b>Alexander Nanberg</b></sub></a><br /><a href="https://github.com/downshift-js/downshift/commits?author=alexandernanberg" title="Documentation">📖</a> <a href="https://github.com/downshift-js/downshift/commits?author=alexandernanberg" title="Code">💻</a></td>
    </tr>
    <tr>
      <td align="center" valign="top" width="14.28%"><a href="https://httpete.com"><img src="https://avatars2.githubusercontent.com/u/1556430?v=4?s=100" width="100px;" alt="Pete Redmond"/><br /><sub><b>Pete Redmond</b></sub></a><br /><a href="https://github.com/downshift-js/downshift/issues?q=author%3Ahttpete-ire" title="Bug reports">🐛</a></td>
      <td align="center" valign="top" width="14.28%"><a href="https://github.com/Zashy"><img src="https://avatars2.githubusercontent.com/u/1706342?v=4?s=100" width="100px;" alt="Nick Lavin"/><br /><sub><b>Nick Lavin</b></sub></a><br /><a href="https://github.com/downshift-js/downshift/issues?q=author%3AZashy" title="Bug reports">🐛</a> <a href="https://github.com/downshift-js/downshift/commits?author=Zashy" title="Code">💻</a> <a href="https://github.com/downshift-js/downshift/commits?author=Zashy" title="Tests">⚠️</a></td>
      <td align="center" valign="top" width="14.28%"><a href="http://jlongster.com"><img src="https://avatars2.githubusercontent.com/u/17031?v=4?s=100" width="100px;" alt="James Long"/><br /><sub><b>James Long</b></sub></a><br /><a href="https://github.com/downshift-js/downshift/issues?q=author%3Ajlongster" title="Bug reports">🐛</a> <a href="https://github.com/downshift-js/downshift/commits?author=jlongster" title="Code">💻</a></td>
      <td align="center" valign="top" width="14.28%"><a href="http://michaelball.co"><img src="https://avatars0.githubusercontent.com/u/1505907?v=4?s=100" width="100px;" alt="Michael Ball"/><br /><sub><b>Michael Ball</b></sub></a><br /><a href="https://github.com/downshift-js/downshift/issues?q=author%3Acycomachead" title="Bug reports">🐛</a> <a href="https://github.com/downshift-js/downshift/commits?author=cycomachead" title="Code">💻</a> <a href="https://github.com/downshift-js/downshift/commits?author=cycomachead" title="Tests">⚠️</a></td>
      <td align="center" valign="top" width="14.28%"><a href="https://github.com/Julienng"><img src="https://avatars0.githubusercontent.com/u/8990614?v=4?s=100" width="100px;" alt="CAVALEIRO Julien"/><br /><sub><b>CAVALEIRO Julien</b></sub></a><br /><a href="#example-Julienng" title="Examples">💡</a></td>
      <td align="center" valign="top" width="14.28%"><a href="http://www.kimgronqvist.se"><img src="https://avatars1.githubusercontent.com/u/3421067?v=4?s=100" width="100px;" alt="Kim Grönqvist"/><br /><sub><b>Kim Grönqvist</b></sub></a><br /><a href="https://github.com/downshift-js/downshift/commits?author=kimgronqvist" title="Code">💻</a> <a href="https://github.com/downshift-js/downshift/commits?author=kimgronqvist" title="Tests">⚠️</a></td>
      <td align="center" valign="top" width="14.28%"><a href="http://sijietian.com"><img src="https://avatars2.githubusercontent.com/u/3675602?v=4?s=100" width="100px;" alt="Sijie"/><br /><sub><b>Sijie</b></sub></a><br /><a href="https://github.com/downshift-js/downshift/issues?q=author%3Atiansijie" title="Bug reports">🐛</a> <a href="https://github.com/downshift-js/downshift/commits?author=tiansijie" title="Code">💻</a></td>
    </tr>
    <tr>
      <td align="center" valign="top" width="14.28%"><a href="http://dsds.io"><img src="https://avatars0.githubusercontent.com/u/410792?v=4?s=100" width="100px;" alt="Dony Sukardi"/><br /><sub><b>Dony Sukardi</b></sub></a><br /><a href="#example-donysukardi" title="Examples">💡</a> <a href="#question-donysukardi" title="Answering Questions">💬</a> <a href="https://github.com/downshift-js/downshift/commits?author=donysukardi" title="Code">💻</a> <a href="https://github.com/downshift-js/downshift/commits?author=donysukardi" title="Tests">⚠️</a></td>
      <td align="center" valign="top" width="14.28%"><a href="https://dillonmulroy.com"><img src="https://avatars1.githubusercontent.com/u/2755722?v=4?s=100" width="100px;" alt="Dillon Mulroy"/><br /><sub><b>Dillon Mulroy</b></sub></a><br /><a href="https://github.com/downshift-js/downshift/commits?author=dmmulroy" title="Documentation">📖</a></td>
      <td align="center" valign="top" width="14.28%"><a href="https://twitter.com/curtytate"><img src="https://avatars3.githubusercontent.com/u/12440573?v=4?s=100" width="100px;" alt="Curtis Tate Wilkinson"/><br /><sub><b>Curtis Tate Wilkinson</b></sub></a><br /><a href="https://github.com/downshift-js/downshift/commits?author=curtiswilkinson" title="Code">💻</a></td>
      <td align="center" valign="top" width="14.28%"><a href="https://github.com/brikou"><img src="https://avatars3.githubusercontent.com/u/383212?v=4?s=100" width="100px;" alt="Brice BERNARD"/><br /><sub><b>Brice BERNARD</b></sub></a><br /><a href="https://github.com/downshift-js/downshift/issues?q=author%3Abrikou" title="Bug reports">🐛</a> <a href="https://github.com/downshift-js/downshift/commits?author=brikou" title="Code">💻</a></td>
      <td align="center" valign="top" width="14.28%"><a href="https://github.com/xutopia"><img src="https://avatars3.githubusercontent.com/u/14304503?v=4?s=100" width="100px;" alt="Tony Xu"/><br /><sub><b>Tony Xu</b></sub></a><br /><a href="https://github.com/downshift-js/downshift/commits?author=xutopia" title="Code">💻</a></td>
      <td align="center" valign="top" width="14.28%"><a href="http://anthonyng.me"><img src="https://avatars1.githubusercontent.com/u/14035529?v=4?s=100" width="100px;" alt="Anthony Ng"/><br /><sub><b>Anthony Ng</b></sub></a><br /><a href="https://github.com/downshift-js/downshift/commits?author=newyork-anthonyng" title="Documentation">📖</a></td>
      <td align="center" valign="top" width="14.28%"><a href="https://github.com/notruth"><img src="https://avatars2.githubusercontent.com/u/11996139?v=4?s=100" width="100px;" alt="S S"/><br /><sub><b>S S</b></sub></a><br /><a href="#question-notruth" title="Answering Questions">💬</a> <a href="https://github.com/downshift-js/downshift/commits?author=notruth" title="Code">💻</a> <a href="https://github.com/downshift-js/downshift/commits?author=notruth" title="Documentation">📖</a> <a href="#ideas-notruth" title="Ideas, Planning, & Feedback">🤔</a> <a href="https://github.com/downshift-js/downshift/commits?author=notruth" title="Tests">⚠️</a></td>
    </tr>
    <tr>
      <td align="center" valign="top" width="14.28%"><a href="http://austintackaberry.co"><img src="https://avatars0.githubusercontent.com/u/29493001?v=4?s=100" width="100px;" alt="Austin Tackaberry"/><br /><sub><b>Austin Tackaberry</b></sub></a><br /><a href="#question-austintackaberry" title="Answering Questions">💬</a> <a href="https://github.com/downshift-js/downshift/commits?author=austintackaberry" title="Code">💻</a> <a href="https://github.com/downshift-js/downshift/commits?author=austintackaberry" title="Documentation">📖</a> <a href="https://github.com/downshift-js/downshift/issues?q=author%3Aaustintackaberry" title="Bug reports">🐛</a> <a href="#example-austintackaberry" title="Examples">💡</a> <a href="#ideas-austintackaberry" title="Ideas, Planning, & Feedback">🤔</a> <a href="https://github.com/downshift-js/downshift/pulls?q=is%3Apr+reviewed-by%3Aaustintackaberry" title="Reviewed Pull Requests">👀</a> <a href="https://github.com/downshift-js/downshift/commits?author=austintackaberry" title="Tests">⚠️</a></td>
      <td align="center" valign="top" width="14.28%"><a href="https://github.com/jduthon"><img src="https://avatars3.githubusercontent.com/u/4168055?v=4?s=100" width="100px;" alt="Jean Duthon"/><br /><sub><b>Jean Duthon</b></sub></a><br /><a href="https://github.com/downshift-js/downshift/issues?q=author%3Ajduthon" title="Bug reports">🐛</a> <a href="https://github.com/downshift-js/downshift/commits?author=jduthon" title="Code">💻</a></td>
      <td align="center" valign="top" width="14.28%"><a href="http://antontelesh.github.io"><img src="https://avatars3.githubusercontent.com/u/3889580?v=4?s=100" width="100px;" alt="Anton Telesh"/><br /><sub><b>Anton Telesh</b></sub></a><br /><a href="https://github.com/downshift-js/downshift/issues?q=author%3AAntontelesh" title="Bug reports">🐛</a> <a href="https://github.com/downshift-js/downshift/commits?author=Antontelesh" title="Code">💻</a></td>
      <td align="center" valign="top" width="14.28%"><a href="https://github.com/ericedem"><img src="https://avatars3.githubusercontent.com/u/1060669?v=4?s=100" width="100px;" alt="Eric Edem"/><br /><sub><b>Eric Edem</b></sub></a><br /><a href="https://github.com/downshift-js/downshift/commits?author=ericedem" title="Code">💻</a> <a href="https://github.com/downshift-js/downshift/commits?author=ericedem" title="Documentation">📖</a> <a href="#ideas-ericedem" title="Ideas, Planning, & Feedback">🤔</a> <a href="https://github.com/downshift-js/downshift/commits?author=ericedem" title="Tests">⚠️</a></td>
      <td align="center" valign="top" width="14.28%"><a href="https://github.com/indiesquidge"><img src="https://avatars3.githubusercontent.com/u/3409645?v=4?s=100" width="100px;" alt="Austin Wood"/><br /><sub><b>Austin Wood</b></sub></a><br /><a href="#question-indiesquidge" title="Answering Questions">💬</a> <a href="https://github.com/downshift-js/downshift/commits?author=indiesquidge" title="Documentation">📖</a> <a href="https://github.com/downshift-js/downshift/pulls?q=is%3Apr+reviewed-by%3Aindiesquidge" title="Reviewed Pull Requests">👀</a></td>
      <td align="center" valign="top" width="14.28%"><a href="https://github.com/mmmurray"><img src="https://avatars3.githubusercontent.com/u/14275790?v=4?s=100" width="100px;" alt="Mark Murray"/><br /><sub><b>Mark Murray</b></sub></a><br /><a href="#infra-mmmurray" title="Infrastructure (Hosting, Build-Tools, etc)">🚇</a></td>
      <td align="center" valign="top" width="14.28%"><a href="https://github.com/gsimone"><img src="https://avatars0.githubusercontent.com/u/1862172?v=4?s=100" width="100px;" alt="Gianmarco"/><br /><sub><b>Gianmarco</b></sub></a><br /><a href="https://github.com/downshift-js/downshift/issues?q=author%3Agsimone" title="Bug reports">🐛</a> <a href="https://github.com/downshift-js/downshift/commits?author=gsimone" title="Code">💻</a></td>
    </tr>
    <tr>
      <td align="center" valign="top" width="14.28%"><a href="https://github.com/pastr"><img src="https://avatars2.githubusercontent.com/u/6838136?v=4?s=100" width="100px;" alt="Emmanuel Pastor"/><br /><sub><b>Emmanuel Pastor</b></sub></a><br /><a href="#example-pastr" title="Examples">💡</a></td>
      <td align="center" valign="top" width="14.28%"><a href="https://github.com/dalehurwitz"><img src="https://avatars2.githubusercontent.com/u/10345034?v=4?s=100" width="100px;" alt="dalehurwitz"/><br /><sub><b>dalehurwitz</b></sub></a><br /><a href="https://github.com/downshift-js/downshift/commits?author=dalehurwitz" title="Code">💻</a></td>
      <td align="center" valign="top" width="14.28%"><a href="https://github.com/blobor"><img src="https://avatars1.githubusercontent.com/u/4813007?v=4?s=100" width="100px;" alt="Bogdan Lobor"/><br /><sub><b>Bogdan Lobor</b></sub></a><br /><a href="https://github.com/downshift-js/downshift/issues?q=author%3Ablobor" title="Bug reports">🐛</a> <a href="https://github.com/downshift-js/downshift/commits?author=blobor" title="Code">💻</a></td>
      <td align="center" valign="top" width="14.28%"><a href="https://github.com/infiniteluke"><img src="https://avatars0.githubusercontent.com/u/1127238?v=4?s=100" width="100px;" alt="Luke Herrington"/><br /><sub><b>Luke Herrington</b></sub></a><br /><a href="#example-infiniteluke" title="Examples">💡</a></td>
      <td align="center" valign="top" width="14.28%"><a href="https://github.com/drobannx"><img src="https://avatars2.githubusercontent.com/u/6361167?v=4?s=100" width="100px;" alt="Brandon Clemons"/><br /><sub><b>Brandon Clemons</b></sub></a><br /><a href="https://github.com/downshift-js/downshift/commits?author=drobannx" title="Code">💻</a></td>
      <td align="center" valign="top" width="14.28%"><a href="https://github.com/aMollusk"><img src="https://avatars0.githubusercontent.com/u/10591587?v=4?s=100" width="100px;" alt="Kieran"/><br /><sub><b>Kieran</b></sub></a><br /><a href="https://github.com/downshift-js/downshift/commits?author=aMollusk" title="Code">💻</a></td>
      <td align="center" valign="top" width="14.28%"><a href="https://github.com/Brushedoctopus"><img src="https://avatars3.githubusercontent.com/u/11570627?v=4?s=100" width="100px;" alt="Brushedoctopus"/><br /><sub><b>Brushedoctopus</b></sub></a><br /><a href="https://github.com/downshift-js/downshift/issues?q=author%3ABrushedoctopus" title="Bug reports">🐛</a> <a href="https://github.com/downshift-js/downshift/commits?author=Brushedoctopus" title="Code">💻</a></td>
    </tr>
    <tr>
      <td align="center" valign="top" width="14.28%"><a href="http://cameronpedwards.com"><img src="https://avatars3.githubusercontent.com/u/5456216?v=4?s=100" width="100px;" alt="Cameron Edwards"/><br /><sub><b>Cameron Edwards</b></sub></a><br /><a href="https://github.com/downshift-js/downshift/commits?author=cameronprattedwards" title="Code">💻</a> <a href="https://github.com/downshift-js/downshift/commits?author=cameronprattedwards" title="Tests">⚠️</a></td>
      <td align="center" valign="top" width="14.28%"><a href="https://github.com/stereobooster"><img src="https://avatars2.githubusercontent.com/u/179534?v=4?s=100" width="100px;" alt="stereobooster"/><br /><sub><b>stereobooster</b></sub></a><br /><a href="https://github.com/downshift-js/downshift/commits?author=stereobooster" title="Code">💻</a> <a href="https://github.com/downshift-js/downshift/commits?author=stereobooster" title="Tests">⚠️</a></td>
      <td align="center" valign="top" width="14.28%"><a href="https://github.com/1Copenut"><img src="https://avatars0.githubusercontent.com/u/934879?v=4?s=100" width="100px;" alt="Trevor Pierce"/><br /><sub><b>Trevor Pierce</b></sub></a><br /><a href="https://github.com/downshift-js/downshift/pulls?q=is%3Apr+reviewed-by%3A1Copenut" title="Reviewed Pull Requests">👀</a></td>
      <td align="center" valign="top" width="14.28%"><a href="http://xuefei-frank.com"><img src="https://avatars1.githubusercontent.com/u/1334982?v=4?s=100" width="100px;" alt="Xuefei Li"/><br /><sub><b>Xuefei Li</b></sub></a><br /><a href="https://github.com/downshift-js/downshift/commits?author=franklixuefei" title="Code">💻</a></td>
      <td align="center" valign="top" width="14.28%"><a href="https://hyperlab.se"><img src="https://avatars0.githubusercontent.com/u/7252803?v=4?s=100" width="100px;" alt="Alfred Ringstad"/><br /><sub><b>Alfred Ringstad</b></sub></a><br /><a href="https://github.com/downshift-js/downshift/commits?author=alfredringstad" title="Code">💻</a></td>
      <td align="center" valign="top" width="14.28%"><a href="https://github.com/dovidweisz"><img src="https://avatars0.githubusercontent.com/u/6895497?v=4?s=100" width="100px;" alt="D[oa]vid Weisz"/><br /><sub><b>D[oa]vid Weisz</b></sub></a><br /><a href="https://github.com/downshift-js/downshift/commits?author=dovidweisz" title="Code">💻</a></td>
      <td align="center" valign="top" width="14.28%"><a href="https://github.com/RoystonS"><img src="https://avatars0.githubusercontent.com/u/19773?v=4?s=100" width="100px;" alt="Royston Shufflebotham"/><br /><sub><b>Royston Shufflebotham</b></sub></a><br /><a href="https://github.com/downshift-js/downshift/issues?q=author%3ARoystonS" title="Bug reports">🐛</a> <a href="https://github.com/downshift-js/downshift/commits?author=RoystonS" title="Code">💻</a></td>
    </tr>
    <tr>
      <td align="center" valign="top" width="14.28%"><a href="http://michaeldeboey.be"><img src="https://avatars3.githubusercontent.com/u/6643991?v=4?s=100" width="100px;" alt="Michaël De Boey"/><br /><sub><b>Michaël De Boey</b></sub></a><br /><a href="https://github.com/downshift-js/downshift/commits?author=MichaelDeBoey" title="Code">💻</a></td>
      <td align="center" valign="top" width="14.28%"><a href="https://github.com/EricHenry"><img src="https://avatars3.githubusercontent.com/u/4412771?v=4?s=100" width="100px;" alt="Henry"/><br /><sub><b>Henry</b></sub></a><br /><a href="https://github.com/downshift-js/downshift/commits?author=EricHenry" title="Code">💻</a></td>
      <td align="center" valign="top" width="14.28%"><a href="http://www.greenarrow.me"><img src="https://avatars3.githubusercontent.com/u/2180127?v=4?s=100" width="100px;" alt="Andrew Walton"/><br /><sub><b>Andrew Walton</b></sub></a><br /><a href="https://github.com/downshift-js/downshift/issues?q=author%3Agreen-arrow" title="Bug reports">🐛</a> <a href="https://github.com/downshift-js/downshift/commits?author=green-arrow" title="Code">💻</a> <a href="https://github.com/downshift-js/downshift/commits?author=green-arrow" title="Tests">⚠️</a></td>
      <td align="center" valign="top" width="14.28%"><a href="https://github.com/arthurdenner"><img src="https://avatars0.githubusercontent.com/u/13774309?v=4?s=100" width="100px;" alt="Arthur Denner"/><br /><sub><b>Arthur Denner</b></sub></a><br /><a href="https://github.com/downshift-js/downshift/commits?author=arthurdenner" title="Code">💻</a></td>
      <td align="center" valign="top" width="14.28%"><a href="http://twitter.com/stipsan"><img src="https://avatars2.githubusercontent.com/u/81981?v=4?s=100" width="100px;" alt="Cody Olsen"/><br /><sub><b>Cody Olsen</b></sub></a><br /><a href="https://github.com/downshift-js/downshift/commits?author=stipsan" title="Code">💻</a></td>
      <td align="center" valign="top" width="14.28%"><a href="https://github.com/TLadd"><img src="https://avatars0.githubusercontent.com/u/5084492?v=4?s=100" width="100px;" alt="Thomas Ladd"/><br /><sub><b>Thomas Ladd</b></sub></a><br /><a href="https://github.com/downshift-js/downshift/commits?author=TLadd" title="Code">💻</a></td>
      <td align="center" valign="top" width="14.28%"><a href="https://github.com/lixualinta"><img src="https://avatars3.githubusercontent.com/u/34634369?v=4?s=100" width="100px;" alt="lixualinta"/><br /><sub><b>lixualinta</b></sub></a><br /><a href="https://github.com/downshift-js/downshift/commits?author=lixualinta" title="Code">💻</a></td>
    </tr>
    <tr>
      <td align="center" valign="top" width="14.28%"><a href="https://twitter.com/JCofman"><img src="https://avatars2.githubusercontent.com/u/2118956?v=4?s=100" width="100px;" alt="Jacob Cofman"/><br /><sub><b>Jacob Cofman</b></sub></a><br /><a href="https://github.com/downshift-js/downshift/commits?author=JCofman" title="Code">💻</a></td>
      <td align="center" valign="top" width="14.28%"><a href="https://github.com/jf248"><img src="https://avatars3.githubusercontent.com/u/19275184?v=4?s=100" width="100px;" alt="Joshua Freedman"/><br /><sub><b>Joshua Freedman</b></sub></a><br /><a href="https://github.com/downshift-js/downshift/commits?author=jf248" title="Code">💻</a></td>
      <td align="center" valign="top" width="14.28%"><a href="https://github.com/AmyScript"><img src="https://avatars1.githubusercontent.com/u/24494020?v=4?s=100" width="100px;" alt="Amy"/><br /><sub><b>Amy</b></sub></a><br /><a href="#example-AmyScript" title="Examples">💡</a></td>
      <td align="center" valign="top" width="14.28%"><a href="http://twitter.com/roginfarrer"><img src="https://avatars1.githubusercontent.com/u/9063669?v=4?s=100" width="100px;" alt="Rogin Farrer"/><br /><sub><b>Rogin Farrer</b></sub></a><br /><a href="https://github.com/downshift-js/downshift/commits?author=roginfarrer" title="Code">💻</a></td>
      <td align="center" valign="top" width="14.28%"><a href="https://github.com/rifler"><img src="https://avatars3.githubusercontent.com/u/871583?s=100" width="100px;" alt="Dmitrii Kanatnikov"/><br /><sub><b>Dmitrii Kanatnikov</b></sub></a><br /><a href="https://github.com/downshift-js/downshift/commits?author=rifler" title="Code">💻</a></td>
      <td align="center" valign="top" width="14.28%"><a href="https://github.com/dallonf"><img src="https://avatars2.githubusercontent.com/u/346300?v=4?s=100" width="100px;" alt="Dallon Feldner"/><br /><sub><b>Dallon Feldner</b></sub></a><br /><a href="https://github.com/downshift-js/downshift/issues?q=author%3Adallonf" title="Bug reports">🐛</a> <a href="https://github.com/downshift-js/downshift/commits?author=dallonf" title="Code">💻</a></td>
      <td align="center" valign="top" width="14.28%"><a href="https://samuelfullerthomas.com"><img src="https://avatars2.githubusercontent.com/u/10165959?v=4?s=100" width="100px;" alt="Samuel Fuller Thomas"/><br /><sub><b>Samuel Fuller Thomas</b></sub></a><br /><a href="https://github.com/downshift-js/downshift/commits?author=samuelfullerthomas" title="Code">💻</a></td>
    </tr>
    <tr>
      <td align="center" valign="top" width="14.28%"><a href="http://audiolion.github.io"><img src="https://avatars1.githubusercontent.com/u/2430381?v=4?s=100" width="100px;" alt="Ryan Castner"/><br /><sub><b>Ryan Castner</b></sub></a><br /><a href="https://github.com/downshift-js/downshift/commits?author=audiolion" title="Code">💻</a></td>
      <td align="center" valign="top" width="14.28%"><a href="https://github.com/silviuavram"><img src="https://avatars2.githubusercontent.com/u/11275392?v=4?s=100" width="100px;" alt="Silviu Alexandru Avram"/><br /><sub><b>Silviu Alexandru Avram</b></sub></a><br /><a href="https://github.com/downshift-js/downshift/issues?q=author%3Asilviuavram" title="Bug reports">🐛</a> <a href="https://github.com/downshift-js/downshift/commits?author=silviuavram" title="Code">💻</a> <a href="https://github.com/downshift-js/downshift/commits?author=silviuavram" title="Tests">⚠️</a></td>
      <td align="center" valign="top" width="14.28%"><a href="https://github.com/akronb"><img src="https://avatars1.githubusercontent.com/u/15676655?v=4?s=100" width="100px;" alt="Anton Volkov"/><br /><sub><b>Anton Volkov</b></sub></a><br /><a href="https://github.com/downshift-js/downshift/commits?author=akronb" title="Code">💻</a> <a href="https://github.com/downshift-js/downshift/commits?author=akronb" title="Tests">⚠️</a></td>
      <td align="center" valign="top" width="14.28%"><a href="http://keegan.st"><img src="https://avatars3.githubusercontent.com/u/513363?v=4?s=100" width="100px;" alt="Keegan Street"/><br /><sub><b>Keegan Street</b></sub></a><br /><a href="https://github.com/downshift-js/downshift/issues?q=author%3Akeeganstreet" title="Bug reports">🐛</a> <a href="https://github.com/downshift-js/downshift/commits?author=keeganstreet" title="Code">💻</a></td>
      <td align="center" valign="top" width="14.28%"><a href="http://manueldugue.de"><img src="https://avatars1.githubusercontent.com/u/894149?v=4?s=100" width="100px;" alt="Manuel Dugué"/><br /><sub><b>Manuel Dugué</b></sub></a><br /><a href="https://github.com/downshift-js/downshift/commits?author=mdugue" title="Code">💻</a></td>
      <td align="center" valign="top" width="14.28%"><a href="https://github.com/mkaradeniz"><img src="https://avatars2.githubusercontent.com/u/12477983?v=4?s=100" width="100px;" alt="Max Karadeniz"/><br /><sub><b>Max Karadeniz</b></sub></a><br /><a href="https://github.com/downshift-js/downshift/commits?author=mkaradeniz" title="Code">💻</a></td>
      <td align="center" valign="top" width="14.28%"><a href="https://medium.com/@gonchub"><img src="https://avatars3.githubusercontent.com/u/857221?v=4?s=100" width="100px;" alt="Gonzalo Beviglia"/><br /><sub><b>Gonzalo Beviglia</b></sub></a><br /><a href="https://github.com/downshift-js/downshift/issues?q=author%3AGonchuB" title="Bug reports">🐛</a> <a href="https://github.com/downshift-js/downshift/commits?author=GonchuB" title="Code">💻</a> <a href="https://github.com/downshift-js/downshift/pulls?q=is%3Apr+reviewed-by%3AGonchuB" title="Reviewed Pull Requests">👀</a></td>
    </tr>
    <tr>
      <td align="center" valign="top" width="14.28%"><a href="https://github.com/kilrain"><img src="https://avatars2.githubusercontent.com/u/47700687?v=4?s=100" width="100px;" alt="Brian Kilrain"/><br /><sub><b>Brian Kilrain</b></sub></a><br /><a href="https://github.com/downshift-js/downshift/issues?q=author%3Akilrain" title="Bug reports">🐛</a> <a href="https://github.com/downshift-js/downshift/commits?author=kilrain" title="Code">💻</a> <a href="https://github.com/downshift-js/downshift/commits?author=kilrain" title="Tests">⚠️</a> <a href="https://github.com/downshift-js/downshift/commits?author=kilrain" title="Documentation">📖</a></td>
      <td align="center" valign="top" width="14.28%"><a href="http://www.gzschaler.de"><img src="https://avatars0.githubusercontent.com/u/321265?v=4?s=100" width="100px;" alt="Gerd Zschaler"/><br /><sub><b>Gerd Zschaler</b></sub></a><br /><a href="https://github.com/downshift-js/downshift/commits?author=rincedd" title="Code">💻</a> <a href="https://github.com/downshift-js/downshift/issues?q=author%3Arincedd" title="Bug reports">🐛</a></td>
      <td align="center" valign="top" width="14.28%"><a href="https://github.com/gaskar"><img src="https://avatars1.githubusercontent.com/u/491166?v=4?s=100" width="100px;" alt="Karen Gasparyan"/><br /><sub><b>Karen Gasparyan</b></sub></a><br /><a href="https://github.com/downshift-js/downshift/commits?author=gaskar" title="Code">💻</a></td>
      <td align="center" valign="top" width="14.28%"><a href="https://github.com/kserjey"><img src="https://avatars1.githubusercontent.com/u/19753880?v=4?s=100" width="100px;" alt="Sergey Korchinskiy"/><br /><sub><b>Sergey Korchinskiy</b></sub></a><br /><a href="https://github.com/downshift-js/downshift/issues?q=author%3Akserjey" title="Bug reports">🐛</a> <a href="https://github.com/downshift-js/downshift/commits?author=kserjey" title="Code">💻</a> <a href="https://github.com/downshift-js/downshift/commits?author=kserjey" title="Tests">⚠️</a></td>
      <td align="center" valign="top" width="14.28%"><a href="https://github.com/edygar"><img src="https://avatars.githubusercontent.com/u/566280?v=3?s=100" width="100px;" alt="Edygar Oliveira"/><br /><sub><b>Edygar Oliveira</b></sub></a><br /><a href="https://github.com/downshift-js/downshift/commits?author=edygar" title="Code">💻</a> <a href="https://github.com/downshift-js/downshift/issues?q=author%3Aedygar" title="Bug reports">🐛</a></td>
      <td align="center" valign="top" width="14.28%"><a href="https://github.com/epeicher"><img src="https://avatars1.githubusercontent.com/u/3519124?v=4?s=100" width="100px;" alt="epeicher"/><br /><sub><b>epeicher</b></sub></a><br /><a href="https://github.com/downshift-js/downshift/issues?q=author%3Aepeicher" title="Bug reports">🐛</a></td>
      <td align="center" valign="top" width="14.28%"><a href="https://francoischalifour.com"><img src="https://avatars3.githubusercontent.com/u/6137112?v=4?s=100" width="100px;" alt="François Chalifour"/><br /><sub><b>François Chalifour</b></sub></a><br /><a href="https://github.com/downshift-js/downshift/commits?author=francoischalifour" title="Code">💻</a> <a href="https://github.com/downshift-js/downshift/commits?author=francoischalifour" title="Tests">⚠️</a> <a href="#platform-francoischalifour" title="Packaging/porting to new platform">📦</a></td>
    </tr>
    <tr>
      <td align="center" valign="top" width="14.28%"><a href="https://github.com/maxmalov"><img src="https://avatars2.githubusercontent.com/u/284129?v=4?s=100" width="100px;" alt="Maxim Malov"/><br /><sub><b>Maxim Malov</b></sub></a><br /><a href="https://github.com/downshift-js/downshift/issues?q=author%3Amaxmalov" title="Bug reports">🐛</a> <a href="https://github.com/downshift-js/downshift/commits?author=maxmalov" title="Code">💻</a></td>
      <td align="center" valign="top" width="14.28%"><a href="https://epiqueras.github.io"><img src="https://avatars2.githubusercontent.com/u/19157096?v=4?s=100" width="100px;" alt="Enrique Piqueras"/><br /><sub><b>Enrique Piqueras</b></sub></a><br /><a href="#ideas-epiqueras" title="Ideas, Planning, & Feedback">🤔</a></td>
      <td align="center" valign="top" width="14.28%"><a href="https://twitter.com/layershifter"><img src="https://avatars0.githubusercontent.com/u/14183168?v=4?s=100" width="100px;" alt="Oleksandr Fediashov"/><br /><sub><b>Oleksandr Fediashov</b></sub></a><br /><a href="https://github.com/downshift-js/downshift/commits?author=layershifter" title="Code">💻</a> <a href="#infra-layershifter" title="Infrastructure (Hosting, Build-Tools, etc)">🚇</a> <a href="#ideas-layershifter" title="Ideas, Planning, & Feedback">🤔</a></td>
      <td align="center" valign="top" width="14.28%"><a href="https://github.com/saitonakamura"><img src="https://avatars1.githubusercontent.com/u/1552189?v=4?s=100" width="100px;" alt="Mikhail Bashurov"/><br /><sub><b>Mikhail Bashurov</b></sub></a><br /><a href="https://github.com/downshift-js/downshift/commits?author=saitonakamura" title="Code">💻</a> <a href="https://github.com/downshift-js/downshift/issues?q=author%3Asaitonakamura" title="Bug reports">🐛</a></td>
      <td align="center" valign="top" width="14.28%"><a href="http://www.joshuagodi.com"><img src="https://avatars1.githubusercontent.com/u/870799?v=4?s=100" width="100px;" alt="Joshua Godi"/><br /><sub><b>Joshua Godi</b></sub></a><br /><a href="https://github.com/downshift-js/downshift/commits?author=jgodi" title="Code">💻</a></td>
      <td align="center" valign="top" width="14.28%"><a href="https://github.com/lukyth"><img src="https://avatars3.githubusercontent.com/u/7040242?v=4?s=100" width="100px;" alt="Kanitkorn Sujautra"/><br /><sub><b>Kanitkorn Sujautra</b></sub></a><br /><a href="https://github.com/downshift-js/downshift/issues?q=author%3Alukyth" title="Bug reports">🐛</a> <a href="https://github.com/downshift-js/downshift/commits?author=lukyth" title="Code">💻</a></td>
      <td align="center" valign="top" width="14.28%"><a href="https://github.com/jorgemoya"><img src="https://avatars3.githubusercontent.com/u/196129?v=4?s=100" width="100px;" alt="Jorge Moya"/><br /><sub><b>Jorge Moya</b></sub></a><br /><a href="https://github.com/downshift-js/downshift/commits?author=jorgemoya" title="Code">💻</a> <a href="https://github.com/downshift-js/downshift/issues?q=author%3Ajorgemoya" title="Bug reports">🐛</a></td>
    </tr>
    <tr>
      <td align="center" valign="top" width="14.28%"><a href="https://kubajastrz.com"><img src="https://avatars0.githubusercontent.com/u/6443113?v=4?s=100" width="100px;" alt="Jakub Jastrzębski"/><br /><sub><b>Jakub Jastrzębski</b></sub></a><br /><a href="https://github.com/downshift-js/downshift/commits?author=KubaJastrz" title="Code">💻</a></td>
      <td align="center" valign="top" width="14.28%"><a href="https://github.com/mufasa71"><img src="https://avatars1.githubusercontent.com/u/626420?v=4?s=100" width="100px;" alt="Shukhrat Mukimov"/><br /><sub><b>Shukhrat Mukimov</b></sub></a><br /><a href="https://github.com/downshift-js/downshift/commits?author=mufasa71" title="Code">💻</a></td>
      <td align="center" valign="top" width="14.28%"><a href="http://jhonnymoreira.dev"><img src="https://avatars0.githubusercontent.com/u/2177742?v=4?s=100" width="100px;" alt="Jhonny Moreira"/><br /><sub><b>Jhonny Moreira</b></sub></a><br /><a href="https://github.com/downshift-js/downshift/commits?author=jhonnymoreira" title="Code">💻</a></td>
      <td align="center" valign="top" width="14.28%"><a href="https://github.com/stefanprobst"><img src="https://avatars0.githubusercontent.com/u/20753323?v=4?s=100" width="100px;" alt="stefanprobst"/><br /><sub><b>stefanprobst</b></sub></a><br /><a href="https://github.com/downshift-js/downshift/commits?author=stefanprobst" title="Code">💻</a> <a href="https://github.com/downshift-js/downshift/commits?author=stefanprobst" title="Tests">⚠️</a></td>
      <td align="center" valign="top" width="14.28%"><a href="https://github.com/louisaspicer"><img src="https://avatars1.githubusercontent.com/u/20270031?v=4?s=100" width="100px;" alt="Louisa Spicer"/><br /><sub><b>Louisa Spicer</b></sub></a><br /><a href="https://github.com/downshift-js/downshift/commits?author=louisaspicer" title="Code">💻</a> <a href="https://github.com/downshift-js/downshift/issues?q=author%3Alouisaspicer" title="Bug reports">🐛</a></td>
      <td align="center" valign="top" width="14.28%"><a href="https://neet.love"><img src="https://avatars2.githubusercontent.com/u/19276905?v=4?s=100" width="100px;" alt="Ryō Igarashi"/><br /><sub><b>Ryō Igarashi</b></sub></a><br /><a href="https://github.com/downshift-js/downshift/issues?q=author%3Aneet" title="Bug reports">🐛</a> <a href="https://github.com/downshift-js/downshift/commits?author=neet" title="Code">💻</a></td>
      <td align="center" valign="top" width="14.28%"><a href="http://ryanlue.com/"><img src="https://avatars2.githubusercontent.com/u/12194123?v=4?s=100" width="100px;" alt="Ryan Lue"/><br /><sub><b>Ryan Lue</b></sub></a><br /><a href="https://github.com/downshift-js/downshift/commits?author=rlue" title="Documentation">📖</a></td>
    </tr>
    <tr>
      <td align="center" valign="top" width="14.28%"><a href="https://github.com/mattleonowicz"><img src="https://avatars3.githubusercontent.com/u/9438872?v=4?s=100" width="100px;" alt="Mateusz Leonowicz"/><br /><sub><b>Mateusz Leonowicz</b></sub></a><br /><a href="https://github.com/downshift-js/downshift/commits?author=mattleonowicz" title="Code">💻</a></td>
      <td align="center" valign="top" width="14.28%"><a href="https://github.com/atomicpages"><img src="https://avatars2.githubusercontent.com/u/1824291?v=4?s=100" width="100px;" alt="Dennis Thompson"/><br /><sub><b>Dennis Thompson</b></sub></a><br /><a href="https://github.com/downshift-js/downshift/commits?author=atomicpages" title="Tests">⚠️</a></td>
      <td align="center" valign="top" width="14.28%"><a href="https://mayicodefuture.live"><img src="https://avatars1.githubusercontent.com/u/32408893?v=4?s=100" width="100px;" alt="Maksym Boytsov"/><br /><sub><b>Maksym Boytsov</b></sub></a><br /><a href="https://github.com/downshift-js/downshift/commits?author=mayicodefuture" title="Code">💻</a></td>
      <td align="center" valign="top" width="14.28%"><a href="http://dataart.com"><img src="https://avatars1.githubusercontent.com/u/5685800?v=4?s=100" width="100px;" alt="Sergey Skrynnikov"/><br /><sub><b>Sergey Skrynnikov</b></sub></a><br /><a href="https://github.com/downshift-js/downshift/commits?author=IwalkAlone" title="Code">💻</a> <a href="https://github.com/downshift-js/downshift/commits?author=IwalkAlone" title="Tests">⚠️</a></td>
      <td align="center" valign="top" width="14.28%"><a href="https://www.linkedin.com/in/vvoyer"><img src="https://avatars0.githubusercontent.com/u/123822?v=4?s=100" width="100px;" alt="Vincent Voyer"/><br /><sub><b>Vincent Voyer</b></sub></a><br /><a href="https://github.com/downshift-js/downshift/commits?author=vvo" title="Documentation">📖</a></td>
      <td align="center" valign="top" width="14.28%"><a href="https://github.com/limejoe"><img src="https://avatars2.githubusercontent.com/u/7977551?v=4?s=100" width="100px;" alt="limejoe"/><br /><sub><b>limejoe</b></sub></a><br /><a href="https://github.com/downshift-js/downshift/commits?author=limejoe" title="Code">💻</a> <a href="https://github.com/downshift-js/downshift/issues?q=author%3Alimejoe" title="Bug reports">🐛</a></td>
      <td align="center" valign="top" width="14.28%"><a href="https://github.com/k88manish"><img src="https://avatars2.githubusercontent.com/u/19614770?v=4?s=100" width="100px;" alt="Manish Kumar"/><br /><sub><b>Manish Kumar</b></sub></a><br /><a href="https://github.com/downshift-js/downshift/commits?author=k88manish" title="Code">💻</a></td>
    </tr>
    <tr>
      <td align="center" valign="top" width="14.28%"><a href="https://github.com/fcrezza"><img src="https://avatars2.githubusercontent.com/u/48123020?v=4?s=100" width="100px;" alt="Anang Fachreza"/><br /><sub><b>Anang Fachreza</b></sub></a><br /><a href="https://github.com/downshift-js/downshift/commits?author=fcrezza" title="Documentation">📖</a> <a href="#example-fcrezza" title="Examples">💡</a></td>
      <td align="center" valign="top" width="14.28%"><a href="http://nickdeom.com"><img src="https://avatars2.githubusercontent.com/u/56491159?v=4?s=100" width="100px;" alt="Nick Deom"/><br /><sub><b>Nick Deom</b></sub></a><br /><a href="https://github.com/downshift-js/downshift/commits?author=ndeom" title="Code">💻</a> <a href="https://github.com/downshift-js/downshift/issues?q=author%3Andeom" title="Bug reports">🐛</a></td>
      <td align="center" valign="top" width="14.28%"><a href="https://github.com/clementgarbay"><img src="https://avatars3.githubusercontent.com/u/12433625?v=4?s=100" width="100px;" alt="Clément Garbay"/><br /><sub><b>Clément Garbay</b></sub></a><br /><a href="https://github.com/downshift-js/downshift/commits?author=clementgarbay" title="Code">💻</a></td>
      <td align="center" valign="top" width="14.28%"><a href="https://github.com/KaiminHuang"><img src="https://avatars.githubusercontent.com/u/5600404?v=4?s=100" width="100px;" alt="Kaimin Huang"/><br /><sub><b>Kaimin Huang</b></sub></a><br /><a href="https://github.com/downshift-js/downshift/commits?author=KaiminHuang" title="Code">💻</a> <a href="https://github.com/downshift-js/downshift/issues?q=author%3AKaiminHuang" title="Bug reports">🐛</a></td>
      <td align="center" valign="top" width="14.28%"><a href="http://theredcircuit.com"><img src="https://avatars.githubusercontent.com/u/1242456?v=4?s=100" width="100px;" alt="David Welling"/><br /><sub><b>David Welling</b></sub></a><br /><a href="https://github.com/downshift-js/downshift/commits?author=davewelling" title="Code">💻</a> <a href="https://github.com/downshift-js/downshift/issues?q=author%3Adavewelling" title="Bug reports">🐛</a> <a href="#ideas-davewelling" title="Ideas, Planning, & Feedback">🤔</a> <a href="#research-davewelling" title="Research">🔬</a></td>
      <td align="center" valign="top" width="14.28%"><a href="https://github.com/chandrasekhar1996"><img src="https://avatars.githubusercontent.com/u/33996892?v=4?s=100" width="100px;" alt="chandrasekhar1996"/><br /><sub><b>chandrasekhar1996</b></sub></a><br /><a href="https://github.com/downshift-js/downshift/issues?q=author%3Achandrasekhar1996" title="Bug reports">🐛</a> <a href="https://github.com/downshift-js/downshift/commits?author=chandrasekhar1996" title="Code">💻</a></td>
      <td align="center" valign="top" width="14.28%"><a href="https://github.com/drewbrend"><img src="https://avatars.githubusercontent.com/u/5375799?v=4?s=100" width="100px;" alt="Brendan Drew"/><br /><sub><b>Brendan Drew</b></sub></a><br /><a href="https://github.com/downshift-js/downshift/commits?author=drewbrend" title="Code">💻</a></td>
    </tr>
    <tr>
      <td align="center" valign="top" width="14.28%"><a href="https://github.com/jeanpan"><img src="https://avatars.githubusercontent.com/u/1307026?v=4?s=100" width="100px;" alt="Jean Pan"/><br /><sub><b>Jean Pan</b></sub></a><br /><a href="https://github.com/downshift-js/downshift/commits?author=jeanpan" title="Code">💻</a></td>
      <td align="center" valign="top" width="14.28%"><a href="https://tjenkinson.me"><img src="https://avatars.githubusercontent.com/u/3259993?v=4?s=100" width="100px;" alt="Tom Jenkinson"/><br /><sub><b>Tom Jenkinson</b></sub></a><br /><a href="#infra-tjenkinson" title="Infrastructure (Hosting, Build-Tools, etc)">🚇</a></td>
      <td align="center" valign="top" width="14.28%"><a href="https://github.com/aliceHendicott"><img src="https://avatars.githubusercontent.com/u/40346716?v=4?s=100" width="100px;" alt="Alice Hendicott"/><br /><sub><b>Alice Hendicott</b></sub></a><br /><a href="https://github.com/downshift-js/downshift/commits?author=aliceHendicott" title="Code">💻</a> <a href="https://github.com/downshift-js/downshift/issues?q=author%3AaliceHendicott" title="Bug reports">🐛</a></td>
      <td align="center" valign="top" width="14.28%"><a href="https://github.com/zmdavis"><img src="https://avatars.githubusercontent.com/u/25305144?v=4?s=100" width="100px;" alt="Zach Davis"/><br /><sub><b>Zach Davis</b></sub></a><br /><a href="https://github.com/downshift-js/downshift/commits?author=zmdavis" title="Code">💻</a> <a href="https://github.com/downshift-js/downshift/issues?q=author%3Azmdavis" title="Bug reports">🐛</a></td>
    </tr>
  </tbody>
</table>






This project follows the [all-contributors][all-contributors] specification.
Contributions of any kind welcome!

## LICENSE

MIT

[npm]: https://www.npmjs.com/
[node]: https://nodejs.org
[build-badge]:
  https://img.shields.io/github/actions/workflow/status/downshift-js/downshift/validate.yml?branch=master&logo=github&style=flat-square
[build]:
  https://github.com/downshift-js/downshift/actions?query=workflow%3Avalidate+branch%3Amaster
[coverage-badge]:
  https://img.shields.io/codecov/c/github/downshift-js/downshift.svg?style=flat-square
[coverage]: https://codecov.io/github/downshift-js/downshift
[version-badge]: https://img.shields.io/npm/v/downshift.svg?style=flat-square
[package]: https://www.npmjs.com/package/downshift
[downloads-badge]: https://img.shields.io/npm/dm/downshift.svg?style=flat-square
[npmcharts]: http://npmcharts.com/compare/downshift
[license-badge]: https://img.shields.io/npm/l/downshift.svg?style=flat-square
[license]: https://github.com/downshift-js/downshift/blob/master/LICENSE
[prs-badge]:
  https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=flat-square
[prs]: http://makeapullrequest.com
[chat]: https://gitter.im/downshift-js/downshift
[chat-badge]:
  https://img.shields.io/gitter/room/downshift-js/downshift.svg?style=flat-square
[coc-badge]:
  https://img.shields.io/badge/code%20of-conduct-ff69b4.svg?style=flat-square
[coc]: https://github.com/downshift-js/downshift/blob/master/CODE_OF_CONDUCT.md
[react-badge]:
  https://img.shields.io/badge/%E2%9A%9B%EF%B8%8F-(p)react-00d8ff.svg?style=flat-square
[react]: https://facebook.github.io/react/
[gzip-badge]:
  http://img.badgesize.io/https://unpkg.com/downshift/dist/downshift.umd.min.js?compression=gzip&label=gzip%20size&style=flat-square
[size-badge]:
  http://img.badgesize.io/https://unpkg.com/downshift/dist/downshift.umd.min.js?label=size&style=flat-square
[unpkg-dist]: https://unpkg.com/downshift/dist/
[module-formats-badge]:
  https://img.shields.io/badge/module%20formats-umd%2C%20cjs%2C%20es-green.svg?style=flat-square
[spectrum-badge]: https://withspectrum.github.io/badge/badge.svg
[spectrum]: https://spectrum.chat/downshift
[emojis]: https://github.com/kentcdodds/all-contributors#emoji-key
[all-contributors]: https://github.com/kentcdodds/all-contributors
[ryan]: https://github.com/ryanflorence
[compound-components-lecture]:
  https://courses.reacttraining.com/courses/advanced-react/lectures/3060560
[react-autocomplete]: https://www.npmjs.com/package/react-autocomplete
[jquery-complete]: https://jqueryui.com/autocomplete/
[examples]:
  https://codesandbox.io/search?refinementList%5Btags%5D%5B0%5D=downshift%3Aexample&page=1
[yt-playlist]:
  https://www.youtube.com/playlist?list=PLV5CVI1eNcJh5CTgArGVwANebCrAh2OUE
[jared]: https://github.com/jaredly
[controlled-components-lecture]:
  https://courses.reacttraining.com/courses/advanced-react/lectures/3172720
[react-training]: https://reacttraining.com/
[advanced-react]: https://courses.reacttraining.com/courses/enrolled/200086
[use-a-render-prop]: https://medium.com/@mjackson/use-a-render-prop-50de598f11ce
[semver]: http://semver.org/
[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
[combobox-readme]:
  https://github.com/downshift-js/downshift/tree/master/src/hooks/useCombobox
[tag-group-readme]:
  https://github.com/downshift-js/downshift/tree/master/src/hooks/useTagGroup
[bundle-phobia-link]: https://bundlephobia.com/result?p=downshift@3.4.8
[aria]: https://www.w3.org/TR/wai-aria-practices/
[combobox-aria-example]:
  https://www.w3.org/WAI/ARIA/apg/example-index/combobox/combobox-autocomplete-list.html
[select-aria-example]:
  https://www.w3.org/WAI/ARIA/apg/example-index/combobox/combobox-select-only.html
[docsite]: https://downshift-js.com/
[code-sandbox-try-it-out]:
  https://codesandbox.io/p/sandbox/github/kentcdodds/downshift-examples?file=%2Fsrc%2Fdownshift%2Fordered-examples%2F00-get-root-props-example.js&moduleview=1
[code-sandbox-no-get-root-props]:
  https://codesandbox.io/p/sandbox/github/kentcdodds/downshift-examples?file=%2Fsrc%2Fdownshift%2Fordered-examples%2F01-basic-autocomplete.js&moduleview=1
[migration-guide-v7]:
  https://github.com/downshift-js/downshift/tree/master/src/hooks/MIGRATION_V7.md

---

### Overview (`src/hooks/README.md`)

# Downshift Hooks

A set of hooks to build simple, flexible, WAI-ARIA compliant React dropdown
components. Developed as a follow up on [this issue][hooks-issue] about using
hooks in our API.

## Migration to v7

`useSelect` and `useCombobox` received some changes related to their API and how
they works in version 7, as a conequence of adapting both hooks to the ARIA 1.2
combobox patterns. If you were using _useSelect_ and/or _useCombobox_ previous
to 7.0.0, check the [migration guide][migration-guide] and update if necessary.

## Hooks

Check out one of the hooks below to use in your application and create fully
accessible widgets without any constraint about the UI library used.

### useSelect

For a custom `select` dropdown check out [useSelect][select-readme].

### useCombobox

For a `combobox/autocomplete` input check out [useCombobox][combobox-readme].

### useTagGroup

For a `tag group` that could also be used to build a multiple selection `select`
or a `combobox` with tags, check out [useTagGroup][tag-group-readme].

## Downshift Hooks API talk

[Silviu](https://silviuaavram.com/) delivered a talk about using the Downshift
hooks at the [axe-con][axe-con] 2021 conference. The talk, which is also
[recorded][axe-con-recording], illustrates how to build an accessible select,
combobox, and support multiple selection using Downshift hooks and custom
components from [ChakraUI][chakra-ui]. It offers a brief crash course to:

- build a custom Select.
- build a custom Combobox.
- enhance the Select and Combobox with multiple selection.
- use custom features like control props, the state reducer and action props.

## Roadmap and contributions

Next steps:

- iterate on `useSelect`, `useCombobox`, `useMultipleSelection` to improve them.
- remove the `Downshift` component once the hooks are mature.

[hooks-issue]: https://github.com/downshift-js/downshift/issues/683
[select-readme]:
  https://github.com/downshift-js/downshift/tree/master/src/hooks/useSelect
[combobox-readme]:
  https://github.com/downshift-js/downshift/tree/master/src/hooks/useCombobox
[tag-group-readme]:
  https://github.com/downshift-js/downshift/tree/master/src/hooks/useTagGroup
[migration-guide]:
  https://github.com/downshift-js/downshift/tree/master/src/hooks/MIGRATION_V7.md
[axe-con]: https://www.deque.com/axe-con/
[axe-con-recording]:
  https://www.youtube.com/watch?v=iDEETM9Pa4Q&ab_channel=DequeSystems
[chakra-ui]: https://chakra-ui.com/

---

### Overview (`src/hooks/useCombobox/README.md`)

# useCombobox

## The problem

You have a combobox or autocomplete dropdown in your application and you want it
to be accessible and functional. For consistency reasons you want it to follow
the [ARIA design pattern][combobox-aria-example] for a combobox. You also want
this solution to be simple to use and flexible so you can tailor it further to
your specific needs.

## This solution

`useCombobox` is a React hook that manages all the stateful logic needed to make
the combobox functional and accessible. It returns a set of props that are meant
to be called and their results destructured on the combobox's elements: its
label, toggle button, input, list and list items. The props are similar to the
ones provided by vanilla `<Downshift>` to the children render prop.

These props are called getter props and their return values are destructured as
a set of ARIA attributes and event listeners. Together with the action props and
state props, they create all the stateful logic needed for the combobox to
implement the corresponding ARIA pattern. Every functionality needed should be
provided out-of-the-box: menu toggle, item selection and up/down movement
between them, screen reader support, highlight by character keys etc.

## Types of Autocomplete

By default, our implementation and examples illustrate an autocomplete of type
_list_. This involves performing your own items filtering logic as well as
keeping the _aria_autocomplete_ value returned by the
[getInputProps](#getinputprops).

There are, in total, 3 types of autocomplete you can opt for, and these are as
follows:

- no autocomplete:
  - [ARIA example][combobox-aria-example-none]
  - use _aria-autocomplete="none"_ attribute to override the default value from
    _getInputProps_.
  - do not implement any filtering logic yourself, just render the listbox
    items. Basically, take the [code example](#usage) below, remove the useState
    with items, the onInputValueChange function, pass _colors_ as _items_ prop
    and render the _colors_ if _isOpen_ is _true_.
- list autocomplete:
  - [ARIA example][combobox-aria-example]
  - just use the [example provided below](#usage) or anything equivalent.
  - filtering logic inside the menu is done by the _useCombobox_ consumer.
- list and inline autocomplete:
  - [ARIA example][combobox-aria-example-both]
  - use _aria-autocomplete="both"_ attribute to override the default value from
    _getInputProps_.
  - filtering logic inside the menu is done by the _useCombobox_ consumer.
  - inline autocomplete based on the highlighted item in the menu is also
    performed by the consumer.

## Migration through breaking changes

The hook received breaking changes related to how it works, as well as the API,
starting with v7. They are documented here:

- [v7 migration guide][migration-guide-v7]
- [v8 migration guide][migration-guide-v8]
- [v9 migration guide][migration-guide-v9]

## Table of Contents




- [Usage](#usage)
- [Basic Props](#basic-props)
  - [items](#items)
  - [itemToString](#itemtostring)
  - [onSelectedItemChange](#onselecteditemchange)
  - [stateReducer](#statereducer)
- [Advanced Props](#advanced-props)
  - [isItemDisabled](#isitemdisabled)
  - [initialSelectedItem](#initialselecteditem)
  - [initialIsOpen](#initialisopen)
  - [initialHighlightedIndex](#initialhighlightedindex)
  - [initialInputValue](#initialinputvalue)
  - [defaultSelectedItem](#defaultselecteditem)
  - [defaultIsOpen](#defaultisopen)
  - [defaultHighlightedIndex](#defaulthighlightedindex)
  - [defaultInputValue](#defaultinputvalue)
  - [itemToKey](#itemtokey)
  - [getA11yStatusMessage](#geta11ystatusmessage)
  - [onHighlightedIndexChange](#onhighlightedindexchange)
  - [onIsOpenChange](#onisopenchange)
  - [onInputValueChange](#oninputvaluechange)
  - [onStateChange](#onstatechange)
  - [highlightedIndex](#highlightedindex)
  - [isOpen](#isopen)
  - [selectedItem](#selecteditem)
  - [inputValue](#inputvalue)
  - [id](#id)
  - [labelId](#labelid)
  - [menuId](#menuid)
  - [toggleButtonId](#togglebuttonid)
  - [inputId](#inputid)
  - [getItemId](#getitemid)
  - [environment](#environment)
- [stateChangeTypes](#statechangetypes)
- [Control Props](#control-props)
- [Returned props](#returned-props)
  - [prop getters](#prop-getters)
  - [actions](#actions)
  - [state](#state)
- [Event Handlers](#event-handlers)
  - [Default handlers](#default-handlers)
  - [Customizing Handlers](#customizing-handlers)
- [Examples](#examples)



## Usage

> [Try it out in the browser][sandbox-example]

```
/* Detailed source-code truncated for AI context efficiency. */
```

## Basic Props

This is the list of props that you should probably know about. There are some
[advanced props](#advanced-props) below as well.

### items

> `any[]` | _required_

The main difference from vanilla `Downshift` is that we pass the items we want
to render to the hook as well. Opening the menu with an item already selected
means the hook has to know in advance what items you plan to render and what is
the position of that item in the list. Consequently, there won't be any need for
two state changes: one for opening the menu and one for setting the highlighted
index, like in `Downshift`.

### itemToString

> `function(item: any)` | defaults to: `item => (item ? String(item) : '')`

If your items are stored as, say, objects instead of strings, downshift still
needs a string representation for each one. This is required for accessibility
aria-live messages (e.g., after making a selection).

**Note:** This callback _must_ include a null check: it is invoked with `null`
whenever the user abandons input via `<Esc>`.

### onSelectedItemChange

> `function(changes: object)` | optional, no useful default

Called each time the selected item was changed. Selection can be performed by
item click, Enter Key while item is highlighted or by blurring the menu while an
item is highlighted (Tab, Shift-Tab or clicking away).

- `changes`: These are the properties that actually have changed since the last
  state change. This object is guaranteed to contain the `selectedItem` property
  with the newly selected value. This also has a `type` property which you can
  learn more about in the [`stateChangeTypes`](#statechangetypes) section. This
  property will be part of the actions that can trigger a `selectedItem` change,
  for example `useCombobox.stateChangeTypes.ItemClick`.

### stateReducer

> `function(state: object, actionAndChanges: object)` | optional

**🚨 This is a really handy power feature 🚨**

This function will be called each time `useCombobox` sets its internal state (or
calls your `onStateChange` handler for control props). It allows you to modify
the state change that will take place which can give you fine grain control over
how the component interacts with user updates. It gives you the current state
and the state that will be set, and you return the state that you want to set.

- `state`: The full current state of downshift.
- `actionAndChanges`: Object that contains the action `type`, the `props` passed
  to `useCombobox`, the `changes` suggested by the Downshift default reducer,
  and any action-specific fields (e.g. `altKey`, `key`, `index`). About the
  `type` property you can learn more about in the
  [`stateChangeTypes`](#statechangetypes) section.

```javascript
import {useCombobox} from 'downshift'
import {items} from './utils'

const {getMenuProps, getItemProps, ...rest} = useCombobox({
  items,
  stateReducer,
})

function stateReducer(state, actionAndChanges) {
  const {type, changes} = actionAndChanges
  // this prevents the menu from being closed when the user selects an item with 'Enter' or mouse
  switch (type) {
    case useCombobox.stateChangeTypes.InputKeyDownEnter:
    case useCombobox.stateChangeTypes.ItemClick:
      return {
        ...changes, // default Downshift new state changes on item selection.
        isOpen: state.isOpen, // but keep menu open.
        highlightedIndex: state.highlightedIndex, // with the item highlighted.
      }
    default:
      return changes // otherwise business as usual.
  }
}
```

> NOTE: This is only called when state actually changes. You should not attempt
> use this to handle events. If you wish to handle events, put your event
> handlers directly on the elements (make sure to use the prop getters though!
> For example `<button onBlur={handleBlur} />` should be
> `<button {...getToggleButtonProps({onBlur: handleBlur})} />`). Also, your
> reducer function should be "pure." This means it should do nothing other than
> return the state changes you want to have happen.

## Advanced Props

### isItemDisabled

> `function(item: any, index: number)` | defaults to: `(_item, _index) => false`

If an item needs to be marked as disabled, this function needs to return `true`
for that item. Disabled items will be skipped from keyboard navigation, will not
be selected and will be marked as disabled for screen readers.

### initialSelectedItem

> `any` | defaults to `null`

Pass an item that should be selected when downshift is initialized.

### initialIsOpen

> `boolean` | defaults to `false`

Pass a boolean that sets the open state of the menu when downshift is
initialized.

### initialHighlightedIndex

> `number` | defaults to `-1`

Pass a number that sets the index of the highlighted item when downshift is
initialized.

### initialInputValue

> `string` | defaults to `''`

Pass a string that sets the content of the input when downshift is initialized.

### defaultSelectedItem

> `any` | defaults to `null`

Pass an item that should be selected when downshift is reset.

### defaultIsOpen

> `boolean` | defaults to `false`

Pass a boolean that sets the open state of the menu when downshift is reset or
when an item is selected.

### defaultHighlightedIndex

> `number` | defaults to `-1`

Pass a number that sets the index of the highlighted item when downshift is
reset or when an item is selected.

### defaultInputValue

> `string` | defaults to `''`

Pass a string that sets the content of the input when downshift is reset or when
an item is selected.

### itemToKey

> `function(item: any)` | defaults to: `item => item`

Used to determine the uniqueness of an item when searching for the item or
comparing the item with another. Returns the item itself, by default, so the
comparing/searching is done internally via referential equality.

If using items as objects and their reference will change during use, you can
use the function to generate a unique key for each item, such as an `id` prop.

```js
function itemToKey(item) {
  return item.id
}
```

> This deprecates the "selectedItemChanged" prop. If you are using the prop
> already, make sure you change to "itemToKey" as the former is removed in v9. A
> migration example:

```js
// initial items.
const items = [
  {id: 1, value: 'Apples'},
  {id: 2, value: 'Oranges'},
]
// the same items but with different references, for any reason.
const newItems = [
  {id: 1, value: 'Apples'},
  {id: 2, value: 'Oranges'},
]

// previously, if you probably had something like this.
function selectedItemChanged(item1, item2) {
  return item1.id === item2.id
}

// moving forward, switch to this one.
function itemToKey(item) {
  return item.id
  // and we will do the comparison like: const isChanged = itemToKey(prevSelectedItem) !== itemToKey(nextSelectedItem)
}
```

### getA11yStatusMessage

> `function({/* see below */})` | default messages provided in English

This function is passed as props to a status updating function nested within
that allows you to create your own ARIA statuses. It is called when the state
changes: `selectedItem`, `highlightedIndex`, `inputValue` or `isOpen`.

There is no default function provided anymore since v9, so if there's no prop
passed, no aria live status message is created. An implementation that resembles
the previous default is written below, should you want to keep pre v9 behaviour.

We don't provide this as a default anymore since we consider that screen readers
have been significantly improved and they can convey information about items
count, possible actions and highlighted items only from the HTML markup, without
the need for aria-live regions.

```js
function getA11yStatusMessage(state) {
  if (!state.isOpen) {
    return ''
  }
  // you need to get resultCount and previousResultCount yourself now, since we don't pass them as arguments anymore
  const resultCount = items.length
  const previousResultCount = previousResultCountRef.current

  if (!resultCount) {
    return 'No results are available.'
  }

  if (resultCount !== previousResultCount) {
    return `${resultCount} result${
      resultCount === 1 ? ' is' : 's are'
    } available, use up and down arrow keys to navigate. Press Enter key to select.`
  }

  return ''
}
```

### onHighlightedIndexChange

> `function(changes: object)` | optional, no useful default

Called each time the highlighted item was changed. Items can be highlighted
while hovering the mouse over them or by keyboard keys such as Up Arrow, Down
Arrow, Home and End. Items can also be highlighted by hitting character keys
that are part of their starting string equivalent.

- `changes`: These are the properties that actually have changed since the last
  state change. This object is guaranteed to contain the `highlightedIndex`
  property with the new value. This also has a `type` property which you can
  learn more about in the [`stateChangeTypes`](#statechangetypes) section. This
  property will be part of the actions that can trigger a `highlightedIndex`
  change, for example `useCombobox.stateChangeTypes.InputKeyDownArrowUp`.

### onIsOpenChange

> `function(changes: object)` | optional, no useful default

Called each time the menu is open or closed. Menu can be open by toggle button
click, Enter, Space, Up Arrow or Down Arrow keys. Can be closed by selecting an
item, blur (Tab, Shift-Tab or clicking outside), clicking the toggle button
again or hitting Escape key.

- `changes`: These are the properties that actually have changed since the last
  state change. This object is guaranteed to contain the `isOpen` property with
  the new value. This also has a `type` property which you can learn more about
  in the [`stateChangeTypes`](#statechangetypes) section. This property will be
  part of the actions that can trigger a `isOpen` change, for example
  `useCombobox.stateChangeTypes.ToggleButtonClick`.

### onInputValueChange

> `function(changes: object)` | optional, no useful default

Called each time the value in the input text changes. The input value should
change like any input of type text, at any character key press, `Space`,
`Backspace`, `Escape` etc.

- `changes`: These are the properties that actually have changed since the last
  state change. This object is guaranteed to contain the `inputValue` property
  with the new value. This also has a `type` property which you can learn more
  about in the [`stateChangeTypes`](#statechangetypes) section. This property
  will be part of the actions that can trigger a `inputValue` change, for
  example `useCombobox.stateChangeTypes.InputChange`.

### onStateChange

> `function(changes: object)` | optional, no useful default

This function is called anytime the internal state changes. This can be useful
if you're using downshift as a "controlled" component, where you manage some or
all of the state (e.g., isOpen, selectedItem, highlightedIndex, etc) and then
pass it as props, rather than letting downshift control all its state itself.

- `changes`: These are the properties that actually have changed since the last
  state change. This also has a `type` property which you can learn more about
  in the [`stateChangeTypes`](#statechangetypes) section.

> Tip: This function will be called any time _any_ state is changed. The best
> way to determine whether any particular state was changed, you can use
> `changes.hasOwnProperty('propName')` or use the `on[statePropKey]Change` props
> described above.

> NOTE: This is only called when state actually changes. You should not attempt
> to use this to handle events. If you wish handle events, put your event
> handlers directly on the elements (make sure to use the prop getters though!
> For example: `<button onBlur={handleBlur} />` should be
> `<button {...getToggleButtonProps({onBlur: handleBlur})} />`).

### highlightedIndex

> `number` | **control prop** (read more about this in
> [the Control Props section](#control-props))

The index of the item that should be highlighted when menu is open.

### isOpen

> `boolean` | **control prop** (read more about this in
> [the Control Props section](#control-props))

The open state of the menu.

### selectedItem

> `any` | **control prop** (read more about this in
> [the Control Props section](#control-props))

The item that should be selected.

### inputValue

> `string` | **control prop** (read more about this in
> [the Control Props section](#control-props))

The value to be displayed in the text input.

🚨 Important 🚨

If you use `onInputValueChange`, `onStateChange` or anything similar in order to
update a state variable that will end up controlling `inputValue`, you will
encounter a
[cursor jump issue](https://github.com/downshift-js/downshift/issues/1108).
There's no way to properly fix this in our current `React.useReducer` setup, so
in order to work around the issue, consider the change below.

```jsx
const [value, setValue] = useState('')
const {getInputProps} = useCombobox({
  items: [],
  inputValue: value,
  // change this:
  onInputValueChange: ({inputValue}) => {
    setValue(inputValue)
  },
})

return (
  <input
    {...getInputProps({
      // to this:
      onChange: e => {
        setValue(e.target.value)
      },
    })}
  />
)
```

### id

> `string` | defaults to a generated ID

Used to generate the first part of the `Downshift` id on the elements. You can
override this `id` with one of your own, provided as a prop, or you can override
the `id` for each element altogether using the props below.

### labelId

> `string` | defaults to a generated ID

Used for `aria` attributes and the `id` prop of the element (`label`) you use
[`getLabelProps`](#getlabelprops) with.

### menuId

> `string` | defaults to a generated ID

Used for `aria` attributes and the `id` prop of the element (`ul`) you use
[`getMenuProps`](#getmenuprops) with.

### toggleButtonId

> `string` | defaults to a generated ID

Used for `aria` attributes and the `id` prop of the element (`button`) you use
[`getToggleButtonProps`](#gettogglebuttonprops) with.

### inputId

> `string` | defaults to a generated ID

Used for `aria` attributes and the `id` prop of the element (`input`) you use
[`getInputProps`](#getmenuprops) with.

### getItemId

> `function(index)` | defaults to a function that generates an ID based on the
> index

Used for `aria` attributes and the `id` prop of the element (`li`) you use
[`getItemProps`](#getitemprops) with.

### environment

> `window` | defaults to `window`

This prop is only useful if you're rendering downshift within a different
`window` context from where your JavaScript is running; for example, an iframe
or a shadow-root. If the given context is lacking `document` and/or
`add|removeEventListener` on its prototype (as is the case for a shadow-root)
then you will need to pass in a custom object that is able to provide
[access to these properties](https://gist.github.com/Rendez/1dd55882e9b850dd3990feefc9d6e177)
for downshift.

## stateChangeTypes

There are a few props that expose changes to state
([`onStateChange`](#onstatechange) and [`stateReducer`](#statereducer)). For you
to make the most of these APIs, it's important for you to understand why state
is being changed. To accomplish this, there's a `type` property on the `changes`
object you get. This `type` corresponds to a `stateChangeTypes` property.

The list of all possible values this `type` property can take is defined in
[this file][state-change-file] and is as follows:

- `useCombobox.stateChangeTypes.InputKeyDownArrowDown`
- `useCombobox.stateChangeTypes.InputKeyDownArrowUp`
- `useCombobox.stateChangeTypes.InputKeyDownEscape`
- `useCombobox.stateChangeTypes.InputKeyDownHome`
- `useCombobox.stateChangeTypes.InputKeyDownEnd`
- `useCombobox.stateChangeTypes.InputKeyDownPageUp`
- `useCombobox.stateChangeTypes.InputKeyDownPadeDown`
- `useCombobox.stateChangeTypes.InputKeyDownEnter`
- `useCombobox.stateChangeTypes.InputChange`
- `useCombobox.stateChangeTypes.InputClick`
- `useCombobox.stateChangeTypes.InputBlur`
- `useCombobox.stateChangeTypes.MenuMouseLeave`
- `useCombobox.stateChangeTypes.ItemMouseMove`
- `useCombobox.stateChangeTypes.ItemClick`
- `useCombobox.stateChangeTypes.ToggleButtonClick`
- `useCombobox.stateChangeTypes.FunctionToggleMenu`
- `useCombobox.stateChangeTypes.FunctionOpenMenu`
- `useCombobox.stateChangeTypes.FunctionCloseMenu`
- `useCombobox.stateChangeTypes.FunctionSetHighlightedIndex`
- `useCombobox.stateChangeTypes.FunctionSelectItem`
- `useCombobox.stateChangeTypes.FunctionSetInputValue`
- `useCombobox.stateChangeTypes.FunctionReset`

See [`stateReducer`](#statereducer) for a concrete example on how to use the
`type` property.

## Control Props

Downshift manages its own state internally and calls your
`onSelectedItemChange`, `onIsOpenChange`, `onHighlightedIndexChange`,
`onInputChange` and `onStateChange` handlers with any relevant changes. The
state that downshift manages includes: `isOpen`, `selectedItem`, `inputValue`
and `highlightedIndex`. Returned action function (read more below) can be used
to manipulate this state and can likely support many of your use cases.

However, if more control is needed, you can pass any of these pieces of state as
a prop (as indicated above) and that state becomes controlled. As soon as
`this.props[statePropKey] !== undefined`, internally, `downshift` will determine
its state based on your prop's value rather than its own internal state. You
will be required to keep the state up to date (this is where `onStateChange`
comes in really handy), but you can also control the state from anywhere, be
that state from other components, `redux`, `react-router`, or anywhere else.

> Note: This is very similar to how normal controlled components work elsewhere
> in react (like `<input />`). If you want to learn more about this concept, you
> can learn about that from the [Advanced React Component Patterns
> course][advanced-react-component-patterns-course]

## Returned props

You use the hook like so:

```javascript
import {useCombobox} from 'downshift'
import {items} from './utils'

const {getInputProps, reset, ...rest} = useCombobox({
  items,
  ...otherProps,
})

return (
  <div>
    <input {...getInputProps()} />
    {/* render the menu and items */}
    {/* render a button that resets the select to defaults */}
    <button
      onClick={() => {
        reset()
      }}
    >
      Reset
    </button>
  </div>
)
```

> NOTE: In this example we used both a getter prop `getInputProps` and an action
> prop `reset`. The properties of `useCombobox` can be split into three
> categories as indicated below:

### prop getters

> See [the blog post about prop getters][blog-post-prop-getters]

> NOTE: These prop-getters provide `aria-` attributes which are very important
> to your component being accessible. It's recommended that you utilize these
> functions and apply the props they give you to your components.

These functions are used to apply props to the elements that you render. This
gives you maximum flexibility to render what, when, and wherever you like. You
call these on the element in question, for example on the toggle button:
`<button {...getToggleButtonProps()}`. It's advisable to pass all your props to
that function rather than applying them on the element yourself to avoid your
props being overridden (or overriding the props returned). For example:
`getToggleButtonProps({onKeyDown(event) {console.log(event)}})`.



| property               | type           | description                                                                                    |
| ---------------------- | -------------- | ---------------------------------------------------------------------------------------------- |
| `getToggleButtonProps` | `function({})` | returns the props you should apply to any menu toggle button element you render.               |
| `getItemProps`         | `function({})` | returns the props you should apply to any menu item elements you render.                       |
| `getLabelProps`        | `function({})` | returns the props you should apply to the `label` element that you render.                     |
| `getMenuProps`         | `function({})` | returns the props you should apply to the `ul` element (or root of your menu) that you render. |
| `getInputProps`        | `function({})` | returns the props you should apply to the `input` element that you render.                     |

#### `getLabelProps`

This method should be applied to the `label` you render. It will generate an
`id` that will be used to label the toggle button and the menu.

There are no required properties for this method.

> Note: For accessibility purposes, calling this method is highly recommended.

#### `getMenuProps`

This method should be applied to the element which contains your list of items.
Typically, this will be a `<div>` or a `<ul>` that surrounds a `map` expression.
This handles the proper ARIA roles and attributes.

Optional properties:

- `refKey`: if you're rendering a composite component, that component will need
  to accept a prop which it forwards to the root DOM element. Commonly, folks
  call this `innerRef`. So you'd call: `getMenuProps({refKey: 'innerRef'})` and
  your composite component would forward like: `<ul ref={props.innerRef} />`.
  However, if you are just rendering a primitive component like `<div>`, there
  is no need to specify this property. It defaults to `ref`.

  Please keep in mind that menus, for accessiblity purposes, should always be
  rendered, regardless of whether you hide it or not. Otherwise, `getMenuProps`
  may throw error if you unmount and remount the menu.

- `aria-label`: By default the menu will add an `aria-labelledby` that refers to
  the `<label>` rendered with `getLabelProps`. However, if you provide
  `aria-label` to give a more specific label that describes the options
  available, then `aria-labelledby` will not be provided and screen readers can
  use your `aria-label` instead.

In some cases, you might want to completely bypass the `refKey` check. Then you
can provide the object `{suppressRefError : true}` as the second argument to
`getMenuProps`. **Please use it with extreme care and only if you are absolutely
sure that the ref is correctly forwarded otherwise `useCombobox` will
unexpectedly fail.**

```jsx
const {getMenuProps} = useCombobox({items})
const ui = (
  <ul {...getMenuProps()}>
    {!isOpen
      ? null
      : items.map((item, index) => (
          <li {...getItemProps({item, index, key: item.id})}>{item.name}</li>
        ))}
  </ul>
)
```

> Note that for accessibility reasons it's best if you always render this
> element whether or not downshift is in an `isOpen` state.

#### `getItemProps`

The props returned from calling this function should be applied to any menu
items you render.

**This is an impure function**, so it should only be called when you will
actually be applying the props to an item.

<details>

<summary>What do you mean by impure function?</summary>

Basically just don't do this:

```jsx
items.map((item, index) => {
  const props = getItemProps({item, index}) // we're calling it here
  if (!shouldRenderItem(item)) {
    return null // but we're not using props, and downshift thinks we are...
  }
  return <div {...props} />
})
```

Instead, you could do this:

```jsx
items.filter(shouldRenderItem).map(item => <div {...getItemProps({item})} />)
```

</details>

Required properties:

The main difference from vanilla `Downshift` is that we require the items as
props before rendering. The reason is to open the menu with items already
highlighted, and we need to know the items before the actual render. It is still
required to pass either `item` or `index` to `getItemProps`.

- `item`: this is the item data that will be selected when the user selects a
  particular item.
- `index`: This is how `downshift` keeps track of your item when updating the
  `highlightedIndex` as the user keys around. By default, `downshift` will
  assume the `index` is the order in which you're calling `getItemProps`. This
  is often good enough, but if you find odd behavior, try setting this
  explicitly. It's probably best to be explicit about `index` when using a
  windowing library like `react-virtualized`.

Optional properties:

- `ref`: if you need to access the item element via a ref object, you'd call the
  function like this: `getItemProps({ref: yourItemRef})`. As a result, the item
  element will receive a composed `ref` property, which guarantees that both
  your code and `useCombobox` use the same correct reference to the element.

- `refKey`: if you're rendering a composite component, that component will need
  to accept a prop which it forwards to the root DOM element. Commonly, folks
  call this `innerRef`. So you'd call: `getItemProps({refKey: 'innerRef'})` and
  your composite component would forward like: `<li ref={props.innerRef} />`.
  However, if you are just rendering a primitive component like `<div>`, there
  is no need to specify this property. It defaults to `ref`.

#### `getToggleButtonProps`

Call this and apply the returned props to a `button`. It allows you to toggle
the `Menu` component.

Optional properties:

- `ref`: if you need to access the button element via a ref object, you'd call
  the function like this: `getToggleButton({ref: yourButtonRef})`. As a result,
  the button element will receive a composed `ref` property, which guarantees
  that both your code and `useCombobox` use the same correct reference to the
  element.

- `refKey`: if you're rendering a composite component, that component will need
  to accept a prop which it forwards to the root DOM element. Commonly, folks
  call this `innerRef`. So you'd call: `getToggleButton({refKey: 'innerRef'})`
  and your composite component would forward like:
  `<button ref={props.innerRef} />`. However, if you are just rendering a
  primitive component like `<div>`, there is no need to specify this property.
  It defaults to `ref`.

- `disabled`: If this is set to `true`, then all of the downshift button event
  handlers will be omitted (it won't toggle the menu when clicked).

```jsx
const {getToggleButtonProps} = useCombobox({items})
const myButton = (
  <button {...getToggleButtonProps()}>Click me</button>
  {/* menu and items */}
)
```

#### `getInputProps`

This method should be applied to the `input` you render. It is recommended that
you pass all props as an object to this method which will compose together any
of the event handlers you need to apply to the `input` while preserving the ones
that `downshift` needs to apply to make the `input` behave.

There are no required properties for this method.

Optional properties:

- `disabled`: If this is set to true, then no event handlers will be returned
  from `getInputProps` and a `disabled` prop will be returned (effectively
  disabling the input).

- `ref`: if you need to access the input element via a ref object, you'd call
  the function like this: `getInputProps({ref: yourInputRef})`. As a result, the
  input element will receive a composed `ref` property, which guarantees that
  both your code and `useCombobox` use the same correct reference to the
  element.

- `refKey`: if you're rendering a composite component, that component will need
  to accept a prop which it forwards to the root DOM element. Commonly, folks
  call this `innerRef`. So you'd call: `getInputProps({refKey: 'innerRef'})` and
  your composite component would forward like: `<input ref={props.innerRef} />`.
  However, if you are just rendering a primitive component like `<div>`, there
  is no need to specify this property. It defaults to `ref`.

- `aria-label`: By default the input will add an `aria-labelledby` that refers
  to the `<label>` rendered with `getLabelProps`. However, if you provide
  `aria-label` to give a more specific label that describes the options
  available, then `aria-labelledby` will not be provided and screen readers can
  use your `aria-label` instead.

In some cases, you might want to completely bypass the `refKey` check. Then you
can provide the object `{suppressRefError : true}` as the second argument to
`getInput`. **Please use it with extreme care and only if you are absolutely
sure that the ref is correctly forwarded otherwise `useCombobox` will
unexpectedly fail.**

### actions

These are functions you can call to change the state of the downshift
`useCombobox` hook.



| property              | type                      | description                                           |
| --------------------- | ------------------------- | ----------------------------------------------------- |
| `closeMenu`           | `function()`              | closes the menu                                       |
| `openMenu`            | `function()`              | opens the menu                                        |
| `selectItem`          | `function(item: any)`     | selects the given item                                |
| `setHighlightedIndex` | `function(index: number)` | call to set a new highlighted index                   |
| `setInputValue`       | `function(value: string)` | call to set a new value in the input                  |
| `toggleMenu`          | `function()`              | toggle the menu open state                            |
| `reset`               | `function()`              | this resets downshift's state to a reasonable default |

### state

These are values that represent the current state of the downshift component.



| property           | type      | description                       |
| ------------------ | --------- | --------------------------------- |
| `highlightedIndex` | `number`  | the currently highlighted item    |
| `isOpen`           | `boolean` | the menu open state               |
| `selectedItem`     | `any`     | the currently selected item input |
| `inputValue`       | `string`  | the value in the input            |

## Event Handlers

Downshift has a few events for which it provides implicit handlers. Several of
these handlers call `event.preventDefault()`. Their additional functionality is
described below.

### Default handlers

#### Toggle Button

- `Click`: If the menu is not displayed, it will open it. Otherwise it will
  close it. It will additionally move focus on the input in order for screen
  readers to correctly narrate which item is currently highlighted. If there is
  already an item selected, the menu will be opened with that item already
  highlighted.
- `Enter`: Has the same effect as `Click`. Button not in the tab order by
  default.
- `Space`: Has the same effect as `Click`. Button not in the tab order by
  default.

#### Input

- `ArrowDown`: Moves `highlightedIndex` one position down. When reaching the
  last option, `ArrowDown` will move `highlightedIndex` to first position.
- `ArrowUp`: Moves `highlightedIndex` one position up. When reaching the first
  option, `ArrowUp` will move `highlightedIndex` to last position.
- `Alt+ArrowDown`: If the menu is closed, it will open it, without highlighting
  any item.
- `Alt+ArrowUp`: If the menu is open, it will close it and will select the item
  that was highlighted.
- `CharacterKey`: Will change the `inputValue` according to the value visible in
  the `<input>`. `Backspace` or `Space` trigger the same event.
- `End`: If the menu is open, it will highlight the last item in the list.
- `Home`: If the menu is open, it will highlight the first item in the list.
- `PageUp`: If the menu is open, it will move the highlight the item 10
  positions before the current selection.
- `PageDown`: If the menu is open, it will move the highlight the item 10
  positions after the current selection.
- `Enter`: If there is a highlighted option, it will select it and close the
  menu.
- `Escape`: It will close the menu if open. If the menu is closed, it will clear
  selection: the value in the `input` will become an empty string and the item
  stored as `selectedItem` will become `null`.
- `Click`: If the menu is closed, it will open it. If the menu is open, it will
  close it.
- `Blur(Tab, Shift+Tab)`: It will close the menu and select the highlighted
  item, if any. The focus will move naturally to the next/previous element in
  the Tab order.
- `Blur(mouse click outside)`: It will close the menu without selecting any
  element, even if there is one highlighted.

#### Menu

- `MouseLeave`: Will clear the value of the `highlightedIndex` if it was set.

#### Item

- `Click`: It will select the item, close the menu and move focus to the toggle
  button (unless `defaultIsOpen` is true).
- `MouseOver`: It will highlight the item.

### Customizing Handlers

You can provide your own event handlers to `useCombobox` which will be called
before the default handlers:

```javascript
const items = [...] // items here.
const {getMenuProps} = useCombobox({items})
const ui = (
  /* button, label, ... */
  <ul
    {...getMenuProps({
      onKeyDown: event => {
        // your custom keyDown handler here.
      },
    })}
  />
)
```

If you would like to prevent the default handler behavior in some cases, you can
set the event's `preventDownshiftDefault` property to `true`:

```javascript
const {getMenuProps} = useCombobox({items})
const ui = (
  /* button, label, ... */
  <ul
    {...getMenuProps({
      onKeyDown: event => {
        // your custom keyDown handler here.
        if (event.key === 'Enter') {
          // Prevent Downshift's default 'Enter' behavior.
          event.nativeEvent.preventDownshiftDefault = true

          // your handler code
        }
      },
    })}
  />
)
```

If you would like to completely override Downshift's behavior for a handler, in
favor of your own, you can bypass prop getters:

```javascript
const items = [...] // items here.
const {getMenuProps} = useCombobox({items})
const ui = (
  /* button, label, ... */
  <ul
    {...getMenuProps()}
    onKeyDown={event => {
      // your custom keyDown handler here.
    }}
  />
)
```

## Examples

Usage examples are kept on the [downshift docsite][docsite] and also on [the
sandbox repo][sandbox-repo]. Each example has a link to its own Codesandbox
version, so check the docs.

It can be a great contributing opportunity to provide relevant use cases as
docsite examples. If you have such an example, please create an issue with the
suggestion and the Codesandbox for it, and we will take it from there.

[combobox-aria-example]:
  https://www.w3.org/WAI/ARIA/apg/example-index/combobox/combobox-autocomplete-list.html
[combobox-aria-example-none]:
  https://www.w3.org/WAI/ARIA/apg/example-index/combobox/combobox-autocomplete-none.html
[combobox-aria-example-both]:
  https://www.w3.org/WAI/ARIA/apg/example-index/combobox/combobox-autocomplete-both.html
[sandbox-example]:
  https://codesandbox.io/p/sandbox/github/kentcdodds/downshift-examples?file=%2Fsrc%2Fhooks%2FuseCombobox%2Fbasic-usage.js&moduleview=1
[state-change-file]:
  https://github.com/downshift-js/downshift/blob/master/src/hooks/useCombobox/stateChangeTypes.js
[blog-post-prop-getters]:
  https://blog.kentcdodds.com/how-to-give-rendering-control-to-users-with-prop-getters-549eaef76acf
[docsite]: https://downshift-js.com/
[sandbox-repo]:
  https://codesandbox.io/p/sandbox/github/kentcdodds/downshift-examples?file=%2Fsrc%2Findex.js&moduleview=1
[advanced-react-component-patterns-course]:
  https://github.com/downshift-js/downshift#advanced-react-component-patterns-course
[migration-guide-v7]:
  https://github.com/downshift-js/downshift/tree/master/src/hooks/MIGRATION_V7.md#usecombobox
[migration-guide-v8]:
  https://github.com/downshift-js/downshift/tree/master/src/hooks/MIGRATION_V8.md
[migration-guide-v9]:
  https://github.com/downshift-js/downshift/tree/master/src/hooks/MIGRATION_V9.md

---

### Overview (`src/hooks/useMultipleSelection/README.md`)

# useMultipleSelection

## Deprecated: migration to useTagGroup

If you're considering a multiple selection solution with tags, check
[useTagGroup][use-tag-group].

If you're already using the hook, migrate to `useTagGroup`. It's meant to offer
a more intuitive and extensible API than `useMultipleSelection`. The
[migration-guide][migration-guide] shows how to migrate to the new hook.

## The problem

You have a custom `select` or a `combobox` in your applications which performs a
multiple selection. You want want the whole experience to be accessible,
including adding and removing items from selection, navigating between the items
and back to the dropdown. You also want this solution to be simple to use and
flexible so you can tailor it further to your specific needs.

## This solution

`useMultipleSelection` is a React hook that manages all the stateful logic
needed to make the multiple selection dropdown functional and accessible. It
returns a set of props that are meant to be called and their results
destructured on the dropdown's elements that involve the multiple selection
experience: the dropdown main element itself, which can be either an `input` (if
you are building a `combobox`) or a `button` (if you are building a `select`),
and the selected items. The props are similar to the ones provided by vanilla
`Downshift` to the children render prop.

These props are called getter props and their return values are destructured as
a set of ARIA attributes and event listeners. Together with the action props and
state props, they create all the stateful logic needed for the dropdown to
become accessible. Every functionality needed should be provided out-of-the-box:
arrow navigation between dropdown and items, navigation between the items
themselves, removing and adding items, and also helpful `aria-live` messages
such as when an item has been removed from selection.

## Migration through breaking changes

The hook received breaking changes related to how it works, as well as the API,
starting with v8. They are documented here:

- [v8 migration guide][migration-guide-v8]
- [v9 migration guide][migration-guide-v9]

## Table of Contents




- [Usage](#usage)
- [Basic Props](#basic-props)
  - [onSelectedItemsChange](#onselecteditemschange)
  - [stateReducer](#statereducer)
- [Advanced Props](#advanced-props)
  - [keyNavigationNext](#keynavigationnext)
  - [keyNavigationPrevious](#keynavigationprevious)
  - [initialSelectedItems](#initialselecteditems)
  - [initialActiveIndex](#initialactiveindex)
  - [defaultSelectedItems](#defaultselecteditems)
  - [defaultActiveIndex](#defaultactiveindex)
  - [itemToKey](#itemtokey)
  - [getA11yStatusMessage](#geta11ystatusmessage)
  - [onActiveIndexChange](#onactiveindexchange)
  - [onStateChange](#onstatechange)
  - [activeIndex](#activeindex)
  - [selectedItems](#selecteditems)
  - [environment](#environment)
- [stateChangeTypes](#statechangetypes)
- [Control Props](#control-props)
- [Returned props](#returned-props)
  - [prop getters](#prop-getters)
  - [actions](#actions)
  - [state](#state)
- [Event Handlers](#event-handlers)
  - [Default handlers](#default-handlers)
  - [Customizing Handlers](#customizing-handlers)
- [Examples](#examples)



## Usage

> [Try it out in the browser][sandbox-example]

```
/* Detailed source-code truncated for AI context efficiency. */
```

The equivalent example with `useSelect` is [here][select-sandbox-example].

## Basic Props

This is the list of props that you should probably know about. There are some
[advanced props](#advanced-props) below as well.

### onSelectedItemsChange

> `function(changes: object)` | optional, no useful default

Called each time the selected items array changes. Especially useful when items
are removed, as there are many ways to do that: `Backspace` from dropdown,
`Backspace` or `Delete` while focus is the item, executing `removeSelectedItem`
when clicking an associated `X` icon for the item.

- `changes`: These are the properties that actually have changed since the last
  state change. This object is guaranteed to contain the `selectedItems`
  property with the new array value. This also has a `type` property which you
  can learn more about in the [`stateChangeTypes`](#statechangetypes) section.
  This property will be part of the actions that can trigger an `selectedItems`
  change, for example `useSelect.stateChangeTypes.DropdownKeyDownBackspace`.

### stateReducer

> `function(state: object, actionAndChanges: object)` | optional

**🚨 This is a really handy power feature 🚨**

This function will be called each time `useMultipleSelection` sets its internal
state (or calls your `onStateChange` handler for control props). It allows you
to modify the state change that will take place which can give you fine grain
control over how the component interacts with user updates. It gives you the
current state and the state that will be set, and you return the state that you
want to set.

- `state`: The full current state of downshift.
- `actionAndChanges`: Object that contains the action `type`, props needed to
  return a new state based on that type and the changes suggested by the
  Downshift default reducer. About the `type` property you can learn more about
  in the [`stateChangeTypes`](#statechangetypes) section.

```javascript
import {useMultipleSelection} from 'downshift'
import {items} from './utils'

const {getDropdownProps, getSelectedItemProps, ...rest} = useMultipleSelection({
  initialSelectedItems: [items[0], items[1]],
  stateReducer,
})

function stateReducer(state, actionAndChanges) {
  const {type, changes} = actionAndChanges
  // this adds focus to the dropdown when item is removed by keyboard action.
  switch (type) {
    case useMultipleSelection.stateChangeTypes.SelectedItemKeyDownBackspace:
    case useMultipleSelection.stateChangeTypes.SelectedItemKeyDownDelete:
      return {
        ...changes,
        activeIndex: -1, // the focus will move to the input/button
      }
    default:
      return changes // otherwise business as usual.
  }
}
```

> NOTE: This is only called when state actually changes. You should not attempt
> use this to handle events. If you wish to handle events, put your event
> handlers directly on the elements (make sure to use the prop getters though!
> For example `<button onBlur={handleBlur} />` should be
> `<button {...getToggleButtonProps({onBlur: handleBlur})} />`). Also, your
> reducer function should be "pure." This means it should do nothing other than
> return the state changes you want to have happen.

## Advanced Props

### keyNavigationNext

> `string` | defaults to `ArrowRight`

The navigation key that increments `activeIndex` and moves focus to the selected
item whose index corresponds to the new value. For a `RTL` scenario, a common
overriden value could be `ArrowLeft`. In some scenarios it can be `ArrowDown`.
It mostly depends on the UI the user is presented with.

### keyNavigationPrevious

> `string` | defaults to `ArrowLeft`

The navigation key that decrements `activeIndex` and moves focus to the selected
item whose index corresponds to the new value. Also moves focus from `dropdown`
to item with the last index. For a `RTL` scenario, a common overriden value
could be `ArrowRight`. In some scenarios it can be `ArrowUp`. It mostly depends
on the UI the user is presented with.

### initialSelectedItems

> `any[]` | defaults to `[]`

Pass an initial array of items that are considered to be selected.

### initialActiveIndex

> `number` | defaults to `-1`

Pass a number that sets the index of the focused / active selected item when
downshift is initialized.

### defaultSelectedItems

> `any[]` | defaults to `[]`

Pass an array of items that are going to be used when downshift is reset.

### defaultActiveIndex

> `number` | defaults to `-1`

Pass a number that sets the index of the focused / active selected item when
downshift is reset.

### itemToKey

> `function(item: any)` | defaults to: `item => item`

Used to determine the uniqueness of an item when searching for the item or
comparing the item with another. Returns the item itself, by default, so the
comparing/searching is done internally via referential equality.

If using items as objects and their reference will change during use, you can
use the function to generate a unique key for each item, such as an `id` prop.

```js
// initial items.
const selectedItems = [
  {id: 1, value: 'Apples'},
  {id: 2, value: 'Oranges'},
]
// the same items but with different references, for any reason.
const newSelectedItems = [
  {id: 1, value: 'Apples'},
  {id: 2, value: 'Oranges'},
]

function itemToKey(item) {
  return item.id
  // and we will do the comparison like: const isChanged = itemToKey(prevSelectedItem) !== itemToKey(nextSelectedItem)
}
```

### getA11yStatusMessage

> `function({/* see below */})` | default messages provided in English

This function is passed as props to a status updating function nested within
that allows you to create your own ARIA statuses. It is called when the state
changes: `selectedItem`, `highlightedIndex`, `inputValue` or `isOpen`.

There is no default function provided anymore since v9, so if there's no prop
passed, no aria live status message is created. An implementation that resembles
the previous default is written below, should you want to keep pre v9 behaviour.

We don't provide this as a default anymore since we consider that screen readers
have been significantly improved and they can convey information about items
count, possible actions and highlighted items only from the HTML markup, without
the need for aria-live regions.

```js
function getA11yStatusMessage(state) {
  const {selectedItems} = state

  if (selectedItems.length === previousSelectedItemsRef.current.length) {
    return ''
  }

  const removedSelectedItem = previousSelectedItemsRef.current.find(
    selectedItem =>
      selectedItems.findIndex(
        item => props.itemToKey(item) === props.itemToKey(selectedItem),
      ) < 0,
  )

  // where itemToString is a function that returns the string equivalent for an item.
  return `${itemToString(removedSelectedItem)} has been removed.`
}
```

### onActiveIndexChange

> `function(changes: object)` | optional, no useful default

Called each time the index of the active item changes. When an item becomes
active, it receives focus, so it can receive keyboard events. To change
`activeIndex` you can either click on the item or use navigation keys between
the items and the dropdown.

- `changes`: These are the properties that actually have changed since the last
  state change. This object is guaranteed to contain the `activeIndex` property
  with the new value. This also has a `type` property which you can learn more
  about in the [`stateChangeTypes`](#statechangetypes) section. This property
  will be part of the actions that can trigger a `activeIndex` change, for
  example `useSelect.stateChangeTypes.ItemClick`.

### onStateChange

> `function(changes: object)` | optional, no useful default

This function is called anytime the internal state changes. This can be useful
if you're using downshift as a "controlled" component, where you manage some or
all of the state (e.g. selectedItems and activeIndex) and then pass it as props,
rather than letting downshift control all its state itself.

- `changes`: These are the properties that actually have changed since the last
  state change. This also has a `type` property which you can learn more about
  in the [`stateChangeTypes`](#statechangetypes) section.

> Tip: This function will be called any time _any_ state is changed. The best
> way to determine whether any particular state was changed, you can use
> `changes.hasOwnProperty('propName')` or use the `on[statePropKey]Change` props
> described above.

> NOTE: This is only called when state actually changes. You should not attempt
> to use this to handle events. If you wish handle events, put your event
> handlers directly on the elements (make sure to use the prop getters though!
> For example: `<button onBlur={handleBlur} />` should be
> `<button {...getDropdownProps({onBlur: handleBlur})} />`).

### activeIndex

> `number` | **control prop** (read more about this in
> [the Control Props section](#control-props))

The index of the item that should be active and focused.

### selectedItems

> `any[]` | **control prop** (read more about this in
> [the Control Props section](#control-props))

The items that are considered selected at the time.

### environment

> `window` | defaults to `window`

This prop is only useful if you're rendering downshift within a different
`window` context from where your JavaScript is running; for example, an iframe
or a shadow-root. If the given context is lacking `document` and/or
`add|removeEventListener` on its prototype (as is the case for a shadow-root)
then you will need to pass in a custom object that is able to provide
[access to these properties](https://gist.github.com/Rendez/1dd55882e9b850dd3990feefc9d6e177)
for downshift.

## stateChangeTypes

There are a few props that expose changes to state
([`onStateChange`](#onstatechange) and [`stateReducer`](#statereducer)). For you
to make the most of these APIs, it's important for you to understand why state
is being changed. To accomplish this, there's a `type` property on the `changes`
object you get. This `type` corresponds to a `stateChangeTypes` property.

The list of all possible values this `type` property can take is defined in
[this file][state-change-file] and is as follows:

- `useMultipleSelection.stateChangeTypes.SelectedItemClick`
- `useMultipleSelection.stateChangeTypes.SelectedItemKeyDownDelete`
- `useMultipleSelection.stateChangeTypes.SelectedItemKeyDownBackspace`
- `useMultipleSelection.stateChangeTypes.SelectedItemKeyDownNavigationNext`
- `useMultipleSelection.stateChangeTypes.SelectedItemKeyDownNavigationPrevious`
- `useMultipleSelection.stateChangeTypes.DropdownKeyDownNavigationPrevious`
- `useMultipleSelection.stateChangeTypes.DropdownKeyDownBackspace`
- `useMultipleSelection.stateChangeTypes.DropdownClick`
- `useMultipleSelection.stateChangeTypes.FunctionAddSelectedItem`
- `useMultipleSelection.stateChangeTypes.FunctionRemoveSelectedItem`
- `useMultipleSelection.stateChangeTypes.FunctionSetSelectedItems`
- `useMultipleSelection.stateChangeTypes.FunctionSetActiveIndex`
- `useMultipleSelection.stateChangeTypes.FunctionReset`

See [`stateReducer`](#statereducer) for a concrete example on how to use the
`type` property.

## Control Props

Downshift manages its own state internally and calls your
`onSelectedItemsChange`, `onActiveIndexChange` and `onStateChange` handlers with
any relevant changes. The state that downshift manages includes: `selectedItems`
and `activeIndex`. Returned action function (read more below) can be used to
manipulate this state and can likely support many of your use cases.

However, if more control is needed, you can pass any of these pieces of state as
a prop (as indicated above) and that state becomes controlled. As soon as
`this.props[statePropKey] !== undefined`, internally, `downshift` will determine
its state based on your prop's value rather than its own internal state. You
will be required to keep the state up to date (this is where `onStateChange`
comes in really handy), but you can also control the state from anywhere, be
that state from other components, `redux`, `react-router`, or anywhere else.

> Note: This is very similar to how normal controlled components work elsewhere
> in react (like `<input />`). If you want to learn more about this concept, you
> can learn about that from this the [Advanced React Component Patterns
> course][advanced-react-component-patterns-course]

## Returned props

You use the hook like so:

```javascript
import {useMultipleSelection} from 'downshift'
import {items} from './utils'

const {getDropdownProps, getSelectedItemProps, selectedItems, reset, ...rest} =
  useMultipleSelection({
    initialSelectedItems: [items[0], [items[1]]],
    ...otherProps,
  })

return (
  <div>
    {/* render the selected items */}
    {selectedItems.map((selectedItem, index) => (
      <span
        key={`selected-item-${index}`}
        {...getSelectedItemProps({selectedItem, index})}
      >
        {selectedItem}
      </span>
    ))}
    {/* render the dropdown itself, with getToggleButtonProps coming from useSelect if you choose to build a <select> with useSelect */}
    <button {...getDropdownProps(getToggleButtonProps())}>
      Select options
    </button>
    {/* render the menu and items */}
    {/* render a button that resets the select to defaults */}
    <button
      onClick={() => {
        reset()
      }}
    >
      Reset
    </button>
  </div>
)
```

> NOTE: In this example we used both the getter props `getSelectedItemProps` and
> `getDropdownProps` and an action prop `reset`. The properties of
> `useMultipleSelection` can be split into three categories as indicated below:

### prop getters

> See [the blog post about prop getters][blog-post-prop-getters]

> NOTE: These prop-getters provide `aria-` attributes which are very important
> to your component being accessible. It's recommended that you utilize these
> functions and apply the props they give you to your components.

These functions are used to apply props to the elements that you render. This
gives you maximum flexibility to render what, when, and wherever you like. You
call these on the element in question, for example on the toggle button:
`<button {...getDropdownProps()}`. It's advisable to pass all your props to that
function rather than applying them on the element yourself to avoid your props
being overridden (or overriding the props returned). For example:
`getDropdownProps({onKeyDown(event) {console.log(event)}})`.

You will most probably use this hook along with `useSelect` or `useCombobox`,
and you can call the getter props from both of them. In the case of `select` you
can call the props on the dropdown like
`getDropdownProps(getToggleButtonProps({onKeyDown(event) {//your custom event}}))`.
Similar story with `combobox` but with `getInputProps` instead of
`getToggleButtonProps`.



| property               | type           | description                                                                                      |
| ---------------------- | -------------- | ------------------------------------------------------------------------------------------------ |
| `getDropdownProps`     | `function({})` | returns the props you should apply to either your input or toggle button, depending on the case. |
| `getSelectedItemProps` | `function({})` | returns the props you should apply to any selected item elements you render.                     |

#### `getSelectedItemProps`

The props returned from calling this function should be applied to any selected
items you render. It allows changing the activeIndex by using arrow keys or by
clicking, but also removing items by `Delete` or `Backspace` on active item. It
also ensures that focus moves along with the activeIndex, and it keeps a
`tabindex="0"` on the active element even if user decides to `Tab` away. That
way, when tabbing back, the user can pick up where he left off with selection.

**This is an impure function**, so it should only be called when you will
actually be applying the props to an item.

<details>

<summary>What do you mean by impure function?</summary>

Basically just don't do this:

```javascript
selectedItems.map((selectedItem, index) => {
  const props = getSelectedItemProps({selectedItem, index}) // we're calling it here
  if (!shouldRenderItem(item)) {
    return null // but we're not using props, and downshift thinks we are...
  }
  return <div {...props} />
})
```

Instead, you could do this:

```jsx
selectedItems
  .filter(shouldRenderItem)
  .map(selectedItem => <div {...getSelectedItemProps({selectedItem})} />)
```

</details>

Required properties:

It is required to pass either `selectedItem` or `index` to
`getSelectedItemProps` in order to be able to apply the activeIndex logic.

- `selectedItem`: this is the item data that will be selected when the user
  selects a particular item.
- `index`: This is how `downshift` keeps track of your item when updating the
  `activeIndex` as the user keys around. By default, `downshift` will assume the
  `index` is the order in which you're calling `getSelectedItemProps`. This is
  often good enough, but if you find odd behavior, try setting this explicitly.
  It's probably best to be explicit about `index` when using a windowing library
  like `react-virtualized`.

Optional properties:

- `ref`: if you need to access the dropdown element via a ref object, you'd call
  the function like this: `getDropdown({ref: yourDropdownRef})`. As a result,
  the dropdown element will receive a composed `ref` property, which guarantees
  that both your code and `useMultipleSelection` use the same correct reference
  to the element.

- `refKey`: if you're rendering a composite component, that component will need
  to accept a prop which it forwards to the root DOM element. Commonly, folks
  call this `innerRef`. So you'd call:
  `getSelectedItemProps({refKey: 'innerRef'})` and your composite component
  would forward like: `<li ref={props.innerRef} />`. However, if you are just
  rendering a primitive component like `<div>`, there is no need to specify this
  property. It defaults to `ref`.

#### `getDropdownProps`

Call this and apply the returned props to a `button` if you are building a
`select` or to an `input` if you're building a `combobox`. It allows you to move
focus from this element to the last item selected by using `ArrowLeft` and also
to remove the last item using `Backspace`.

Optional properties:

- `preventKeyAction`: tells `useMultipleSelection` if `dropdown` is allowed to
  execute `downshift` handlers on `keydown`. For example, you can pass `isOpen`
  as value and user will not be able to delete selecteditems by `Backspace` or
  to navigate to them by arrow keys. This is useful if you don't want to mix key
  actions from multiple selection with the ones from the dropdown. Once the
  dropdown is closed then deletion / navigation can be resumed for multiple
  selection. The value is `false` by default.
- `refKey`: if you're rendering a composite component, that component will need
  to accept a prop which it forwards to the root DOM element. Commonly, folks
  call this `innerRef`. So you'd call: `getDropdownProps({refKey: 'innerRef'})`
  and your composite component would forward like:
  `<button ref={props.innerRef} />`. However, if you are just rendering a
  primitive component like `<div>`, there is no need to specify this property.
  It defaults to `ref`.

In some cases, you might want to completely bypass the `refKey` check. Then you
can provide the object `{suppressRefError : true}` as the second argument to
`getDropdownProps`. **Please use it with extreme care and only if you are
absolutely sure that the ref is correctly forwarded otherwise
`useMultipleSelection` will unexpectedly fail.**

```javascript
const {getDropdownProps} = useMultipleSelection()
const {isOpen, ...rest} = useSelect({items})
const myButton = (
  {/* selected items */}
  <button {...getDropdownProps({preventKeyAction: isOpen})}>Click me</button>
  {/* menu and items */}
)
```

### actions

These are functions you can call to change the state of the downshift
`useMultipleSelection` hook.



| property             | type                      | description                                           |
| -------------------- | ------------------------- | ----------------------------------------------------- |
| `addSelectedItem`    | `function(item: any)`     | adds an item to the selected array                    |
| `removeSelectedItem` | `function(item: any)`     | removes an item from the selected array               |
| `reset`              | `function()`              | resets the selectedItems and active index to defaults |
| `setActiveIndex`     | `function(index: number)` | sets activeIndex to the new value                     |
| `setSelectedItems`   | `function(items: any[])`  | sets selectedItems to the new value                   |

### state

These are values that represent the current state of the downshift component.



| property        | type     | description                           |
| --------------- | -------- | ------------------------------------- |
| `activeIndex`   | `number` | the index of thecurrently active item |
| `selectedItems` | `any[]`  | the items of the selection            |

## Event Handlers

Downshift has a few events for which it provides implicit handlers. Several of
these handlers call `event.preventDefault()`. Their additional functionality is
described below.

### Default handlers

#### Dropdown - button or input

- `ArrowLeft`: Moves focus from `button`/`input` to the last selected item and
  makes `activeIndex` to be `selectedItems.length - 1`. Performs this action if
  there are any items selected. `ArrowLeft` can be overriden with any other key
  depeding on the requirements. More info on
  [`keyNavigationPrevious`](#keynavigationprevious).
- `Backspace`: Removes the last selected item from selection. It always performs
  this action on a non-input element. If the `dropdown` is a `combobox` the text
  cursor of the `input` must be at the start of the `input` and not highlight
  any text in order for the removal to work.

#### Item

- `Click`: It will make the item active, will modify `activeIndex` to reflect
  the new change, and will add focus to that item.
- `Delete`: It will remove the item from selection. `activeIndex` will stay the
  same if the item removed was not the last one, but focus will move to the item
  which now has that index. If the last item was removed, the `activeIndex` will
  decrease by one and will also move focus to the corresponding item. If there
  are no items available anymore, the focus moves to the dropdown and
  `activeIndex` becomes `-1`.
- `Backspace`: Same effect as `Delete`.
- `ArrowLeft`: Moves `activeIndex` and focus to previous item. It stops at the
  first item in the selection. `ArrowLeft` can be overriden with any other key
  depeding on the requirements. More info on
  [`keyNavigationPrevious`](#keynavigationprevious).
- `ArrowRight`: Moves `activeIndex` and focus to next item. It will move focus
  to the `dropdown` if it occurs on the last selected item. `ArrowRight` can be
  overriden with any other key depeding on the requirements. More info on
  [`keyNavigationNext`](#keynavigationnext).

### Customizing Handlers

You can provide your own event handlers to `useMultipleSelection` which will be
called before the default handlers:

```javascript
const items = [...] // items here.
const {getDropdownProps} = useMultipleSelection()
const {getInputProps} = useCombobox({items})
const ui = (
  /* label, selected items, ... */
  <input
    {...getInputProps(
      getDropdownProps({
        onKeyDown: event => {
          // your custom keyDown handler here.
        },
      }),
    )}
  />
)
```

If you would like to prevent the default handler behavior in some cases, you can
set the event's `preventDownshiftDefault` property to `true`:

```javascript
const items = [...] // items here.
const {getDropdownProps} = useMultipleSelection()
const {getInputProps} = useCombobox({items})
const ui = (
  /* label, selected items, ... */
  <input
    {...getInputProps(
      getDropdownProps({
        onKeyDown: event => {
          // your custom keyDown handler here.
          if (event.key === 'Enter') {
            // Prevent Downshift's default 'Enter' behavior.
            event.nativeEvent.preventDownshiftDefault = true

            // your handler code
          }
        },
      }),
    )}
  />
)
```

If you would like to completely override Downshift's behavior for a handler, in
favor of your own, you can bypass prop getters:

```javascript
const items = [...] // items here.
const {getDropdownProps} = useMultipleSelection()
const {getInputProps} = useCombobox({items})
const ui = (
  /* label, selected items, ... */
  <input
    {...getInputProps(
      getDropdownProps({
        onKeyDown: event => {
          // your custom keyDown handler here.
        },
      }),
    )}
    onKeyDown={event => {
      // your custom keyDown handler here.
    }}
  />
)
```

## Examples

Usage examples are kept on the [downshift docsite][docsite] and also on [the
sandbox repo][sandbox-repo]. Each example has a link to its own Codesandbox
version, so check the docs.

It can be a great contributing opportunity to provide relevant use cases as
docsite examples. If you have such an example, please create an issue with the
suggestion and the Codesandbox for it, and we will take it from there.

[sandbox-example]:
  https://codesandbox.io/p/sandbox/github/kentcdodds/downshift-examples?file=%2Fsrc%2Fhooks%2FuseMultipleSelection%2Fcombobox.js&moduleview=1
[select-sandbox-example]:
  https://codesandbox.io/p/sandbox/github/kentcdodds/downshift-examples?file=%2Fsrc%2Fhooks%2FuseMultipleSelection%2Fselect.js&moduleview=1
[state-change-file]:
  https://github.com/downshift-js/downshift/blob/master/src/hooks/useMultipleSelection/stateChangeTypes.js
[blog-post-prop-getters]:
  https://kentcdodds.com/blog/how-to-give-rendering-control-to-users-with-prop-getters-549eaef76acf
[docsite]: https://downshift-js.com/
[sandbox-repo]:
  https://codesandbox.io/p/sandbox/github/kentcdodds/downshift-examples?file=%2Fsrc%2Findex.js&moduleview=1
[advanced-react-component-patterns-course]:
  https://github.com/downshift-js/downshift#advanced-react-component-patterns-course
[migration-guide-v8]:
  https://github.com/downshift-js/downshift/tree/master/src/hooks/MIGRATION_V8.md
[migration-guide-v9]:
  https://github.com/downshift-js/downshift/tree/master/src/hooks/MIGRATION_V9.md
[use-tag-group]:
  https://github.com/downshift-js/downshift/tree/master/src/hooks/useTagGroup/README.md
[migration-guide]:
  https://github.com/downshift-js/downshift/tree/master/src/hooks/useMultipleSelection/MIGRATION_GUIDE.md

---

### Overview (`src/hooks/useSelect/README.md`)

# useSelect

## The problem

You have a custom select dropdown in your application and you want it to behave
exactly the same as the native HTML `<select>` in terms of accessibility and
functionality. For consistency reasons you want it to follow the [ARIA design
pattern][select-aria] for a dropdown select. You also want this solution to be
simple to use and flexible so you can tailor it further to your specific needs.

## This solution

`useSelect` is a React hook that manages all the stateful logic needed to make
the dropdown functional and accessible. It returns a set of props that are meant
to be called and their results destructured on the dropdown's elements: its
label, toggle button, list and list items. The props are similar to the ones
provided by vanilla `<Downshift>` to the children render prop.

These props are called getter props and their return values are destructured as
a set of ARIA attributes and event listeners. Together with the action props and
state props, they create all the stateful logic needed for the dropdown to
implement the corresponding ARIA pattern. Every functionality needed should be
provided out-of-the-box: menu toggle, item selection and up/down movement
between them, screen reader support, highlight by character keys etc.

## Migration through breaking changes

The hook received breaking changes related to how it works, as well as the API,
starting with v7. They are documented here:

- [v7 migration guide][migration-guide-v7]
- [v8 migration guide][migration-guide-v8]
- [v9 migration guide][migration-guide-v9]

## Table of Contents




- [Usage](#usage)
- [Basic Props](#basic-props)
  - [items](#items)
  - [itemToString](#itemtostring)
  - [onSelectedItemChange](#onselecteditemchange)
  - [stateReducer](#statereducer)
- [Advanced Props](#advanced-props)
  - [isItemDisabled](#isitemdisabled)
  - [initialSelectedItem](#initialselecteditem)
  - [initialIsOpen](#initialisopen)
  - [initialHighlightedIndex](#initialhighlightedindex)
  - [defaultSelectedItem](#defaultselecteditem)
  - [defaultIsOpen](#defaultisopen)
  - [defaultHighlightedIndex](#defaulthighlightedindex)
  - [itemToKey](#itemtokey)
  - [getA11yStatusMessage](#geta11ystatusmessage)
  - [onHighlightedIndexChange](#onhighlightedindexchange)
  - [onIsOpenChange](#onisopenchange)
  - [onStateChange](#onstatechange)
  - [highlightedIndex](#highlightedindex)
  - [isOpen](#isopen)
  - [selectedItem](#selecteditem)
  - [id](#id)
  - [labelId](#labelid)
  - [menuId](#menuid)
  - [toggleButtonId](#togglebuttonid)
  - [getItemId](#getitemid)
  - [environment](#environment)
- [stateChangeTypes](#statechangetypes)
- [Control Props](#control-props)
- [Returned props](#returned-props)
  - [prop getters](#prop-getters)
  - [actions](#actions)
  - [state](#state)
- [Event Handlers](#event-handlers)
  - [Default handlers](#default-handlers)
  - [Customizing Handlers](#customizing-handlers)
- [Examples](#examples)



## Usage

> [Try it out in the browser][sandbox-example]

```
/* Detailed source-code truncated for AI context efficiency. */
```

## Basic Props

This is the list of props that you should probably know about. There are some
[advanced props](#advanced-props) below as well.

### items

> `any[]` | _required_

The main difference from vanilla `Downshift` is that we pass the items we want
to render to the hook as well. Opening the menu with an item already selected
means the hook has to know in advance what items you plan to render and what is
the position of that item in the list. Consequently, there won't be any need for
two state changes: one for opening the menu and one for setting the highlighted
index, like in `Downshift`.

### itemToString

> `function(item: any)` | defaults to: `item => (item ? String(item) : '')`

If your items are stored as, say, objects instead of strings, downshift still
needs a string representation for each one. This is required for accessibility
aria-live messages (e.g., after making a selection) and for keyboard interaction
features (e.g., highlighting an item by typing its first few characters).

### onSelectedItemChange

> `function(changes: object)` | optional, no useful default

Called each time the selected item was changed. Selection can be performed by
item click, Enter or Space Key while item is highlighted or by using character
keys while the toggle button is focused and menu is closed.

- `changes`: These are the properties that actually have changed since the last
  state change. This object is guaranteed to contain the `selectedItem` property
  with the newly selected value. This also has a `type` property which you can
  learn more about in the [`stateChangeTypes`](#statechangetypes) section. This
  property will be part of the actions that can trigger a `selectedItem` change,
  for example `useSelect.stateChangeTypes.ItemClick`.

### stateReducer

> `function(state: object, actionAndChanges: object)` | optional

**🚨 This is a really handy power feature 🚨**

This function will be called each time `useSelect` sets its internal state (or
calls your `onStateChange` handler for control props). It allows you to modify
the state change that will take place which can give you fine grain control over
how the component interacts with user updates. It gives you the current state
and the state that will be set, and you return the state that you want to set.

- `state`: The full current state of downshift.
- `actionAndChanges`: Object that contains the action `type`, the `props` passed
  to `useSelect`, the `changes` suggested by the Downshift default reducer, and
  any action-specific fields (e.g. `altKey`, `key`, `index`). About the `type`
  property you can learn more about in the
  [`stateChangeTypes`](#statechangetypes) section.

```javascript
import {useSelect} from 'downshift'
import {items} from './utils'

const {getMenuProps, getItemProps, ...rest} = useSelect({
  items,
  stateReducer,
})

function stateReducer(state, actionAndChanges) {
  const {type, changes} = actionAndChanges
  // this prevents the menu from being closed when the user selects an item with 'Enter' or mouse
  switch (type) {
    case useSelect.stateChangeTypes.ToggleButtonKeyDownEnter:
    case useSelect.stateChangeTypes.ItemClick:
      return {
        ...changes, // default Downshift new state changes on item selection.
        isOpen: state.isOpen, // but keep menu open.
        highlightedIndex: state.highlightedIndex, // with the item highlighted.
      }
    default:
      return changes // otherwise business as usual.
  }
}
```

> NOTE: This is only called when state actually changes. You should not attempt
> use this to handle events. If you wish to handle events, put your event
> handlers directly on the elements (make sure to use the prop getters though!
> For example `<button onBlur={handleBlur} />` should be
> `<button {...getToggleButtonProps({onBlur: handleBlur})} />`). Also, your
> reducer function should be "pure." This means it should do nothing other than
> return the state changes you want to have happen.

## Advanced Props

### isItemDisabled

> `function(item: any, index: number)` | defaults to: `(_item, _index) => false`

If an item needs to be marked as disabled, this function needs to return `true`
for that item. Disabled items will be skipped from keyboard navigation, will not
be selected and will be marked as disabled for screen readers.

### initialSelectedItem

> `any` | defaults to `null`

Pass an item that should be selected when downshift is initialized.

### initialIsOpen

> `boolean` | defaults to `false`

Pass a boolean that sets the open state of the menu when downshift is
initialized.

### initialHighlightedIndex

> `number` | defaults to `-1`

Pass a number that sets the index of the highlighted item when downshift is
initialized.

### defaultSelectedItem

> `any` | defaults to `null`

Pass an item that should be selected when downshift is reset.

### defaultIsOpen

> `boolean` | defaults to `false`

Pass a boolean that sets the open state of the menu when downshift is reset or
when an item is selected.

### defaultHighlightedIndex

> `number` | defaults to `-1`

Pass a number that sets the index of the highlighted item when downshift is
reset or when an item is selected.

### itemToKey

> `function(item: any)` | defaults to: `item => item`

Used to determine the uniqueness of an item when searching for the item or
comparing the item with another. Returns the item itself, by default, so the
comparing/searching is done internally via referential equality.

If using items as objects and their reference will change during use, you can
use the function to generate a unique key for each item, such as an `id` prop.

```js
// initial items.
const items = [
  {id: 1, value: 'Apples'},
  {id: 2, value: 'Oranges'},
]
// the same items but with different references, for any reason.
const newItems = [
  {id: 1, value: 'Apples'},
  {id: 2, value: 'Oranges'},
]

function itemToKey(item) {
  return item.id
  // and we will do the comparison like: const isChanged = itemToKey(prevSelectedItem) !== itemToKey(nextSelectedItem)
}
```

### getA11yStatusMessage

> `function({/* see below */})` | default messages provided in English

This function is passed as props to a status updating function nested within
that allows you to create your own ARIA statuses. It is called when the state
changes: `selectedItem`, `highlightedIndex`, `inputValue` or `isOpen`.

There is no default function provided anymore since v9, so if there's no prop
passed, no aria live status message is created. An implementation that resembles
the previous default is written below, should you want to keep pre v9 behaviour.

We don't provide this as a default anymore since we consider that screen readers
have been significantly improved and they can convey information about items
count, possible actions and highlighted items only from the HTML markup, without
the need for aria-live regions.

```js
function getA11yStatusMessage(state) {
  if (!state.isOpen) {
    return ''
  }
  // you need to get resultCount and previousResultCount yourself now, since we don't pass them as arguments anymore
  const resultCount = items.length
  const previousResultCount = previousResultCountRef.current

  if (!resultCount) {
    return 'No results are available.'
  }

  if (resultCount !== previousResultCount) {
    return `${resultCount} result${
      resultCount === 1 ? ' is' : 's are'
    } available, use up and down arrow keys to navigate. Press Enter or Space Bar keys to select.`
  }

  return ''
}
```

### onHighlightedIndexChange

> `function(changes: object)` | optional, no useful default

Called each time the highlighted item was changed. Items can be highlighted
while hovering the mouse over them or by keyboard keys such as Up Arrow, Down
Arrow, Home and End. Items can also be highlighted by hitting character keys
that are part of their starting string equivalent.

- `changes`: These are the properties that actually have changed since the last
  state change. This object is guaranteed to contain the `highlightedIndex`
  property with the new value. This also has a `type` property which you can
  learn more about in the [`stateChangeTypes`](#statechangetypes) section. This
  property will be part of the actions that can trigger a `highlightedIndex`
  change, for example `useSelect.stateChangeTypes.ToggleButtonKeyDownArrowUp`.

### onIsOpenChange

> `function(changes: object)` | optional, no useful default

Called each time the menu is open or closed. Menu can be open by toggle button
click, Enter, Space, Up Arrow or Down Arrow keys. Can be closed by selecting an
item, blur (Tab, Shift-Tab or clicking outside), clicking the toggle button
again or hitting Escape key.

- `changes`: These are the properties that actually have changed since the last
  state change. This object is guaranteed to contain the `isOpen` property with
  the new value. This also has a `type` property which you can learn more about
  in the [`stateChangeTypes`](#statechangetypes) section. This property will be
  part of the actions that can trigger a `isOpen` change, for example
  `useSelect.stateChangeTypes.ToggleButtonClick`.

### onStateChange

> `function(changes: object)` | optional, no useful default

This function is called anytime the internal state changes. This can be useful
if you're using downshift as a "controlled" component, where you manage some or
all of the state (e.g., isOpen, selectedItem, highlightedIndex, etc) and then
pass it as props, rather than letting downshift control all its state itself.

- `changes`: These are the properties that actually have changed since the last
  state change. This also has a `type` property which you can learn more about
  in the [`stateChangeTypes`](#statechangetypes) section.

> Tip: This function will be called any time _any_ state is changed. The best
> way to determine whether any particular state was changed, you can use
> `changes.hasOwnProperty('propName')` or use the `on[statePropKey]Change` props
> described above.

> NOTE: This is only called when state actually changes. You should not attempt
> to use this to handle events. If you wish handle events, put your event
> handlers directly on the elements (make sure to use the prop getters though!
> For example: `<button onBlur={handleBlur} />` should be
> `<button {...getToggleButtonProps({onBlur: handleBlur})} />`).

### highlightedIndex

> `number` | **control prop** (read more about this in
> [the Control Props section](#control-props))

The index of the item that should be highlighted when menu is open.

### isOpen

> `boolean` | **control prop** (read more about this in
> [the Control Props section](#control-props))

The open state of the menu.

### selectedItem

> `any` | **control prop** (read more about this in
> [the Control Props section](#control-props))

The item that should be selected.

### id

> `string` | defaults to a generated ID

Used to generate the first part of the `Downshift` id on the elements. You can
override this `id` with one of your own, provided as a prop, or you can override
the `id` for each element altogether using the props below.

### labelId

> `string` | defaults to a generated ID

Used for `aria` attributes and the `id` prop of the element (`label`) you use
[`getLabelProps`](#getlabelprops) with.

### menuId

> `string` | defaults to a generated ID

Used for `aria` attributes and the `id` prop of the element (`ul`) you use
[`getMenuProps`](#getmenuprops) with.

### toggleButtonId

> `string` | defaults to a generated ID

Used for `aria` attributes and the `id` prop of the element (`button`) you use
[`getToggleButtonProps`](#gettogglebuttonprops) with.

### getItemId

> `function(index)` | defaults to a function that generates an ID based on the
> index

Used for `aria` attributes and the `id` prop of the element (`li`) you use
[`getItemProps`](#getitemprops) with.

### environment

> `window` | defaults to `window`

This prop is only useful if you're rendering downshift within a different
`window` context from where your JavaScript is running; for example, an iframe
or a shadow-root. If the given context is lacking `document` and/or
`add|removeEventListener` on its prototype (as is the case for a shadow-root)
then you will need to pass in a custom object that is able to provide
[access to these properties](https://gist.github.com/Rendez/1dd55882e9b850dd3990feefc9d6e177)
for downshift.

## stateChangeTypes

There are a few props that expose changes to state
([`onStateChange`](#onstatechange) and [`stateReducer`](#statereducer)). For you
to make the most of these APIs, it's important for you to understand why state
is being changed. To accomplish this, there's a `type` property on the `changes`
object you get. This `type` corresponds to a `stateChangeTypes` property.

The list of all possible values this `type` property can take is defined in
[this file][state-change-file] and is as follows:

- `useSelect.stateChangeTypes.ToggleButtonKeyDownArrowDown`
- `useSelect.stateChangeTypes.ToggleButtonKeyDownArrowUp`
- `useSelect.stateChangeTypes.ToggleButtonKeyDownEscape`
- `useSelect.stateChangeTypes.ToggleButtonKeyDownHome`
- `useSelect.stateChangeTypes.ToggleButtonKeyDownEnd`
- `useSelect.stateChangeTypes.ToggleButtonKeyDownPageUp`
- `useSelect.stateChangeTypes.ToggleButtonKeyDownPageDown`
- `useSelect.stateChangeTypes.ToggleButtonKeyDownEnter`
- `useSelect.stateChangeTypes.ToggleButtonKeyDownSpaceButton`
- `useSelect.stateChangeTypes.ToggleButtonKeyDownCharacter`
- `useSelect.stateChangeTypes.ToggleButtonBlur`
- `useSelect.stateChangeTypes.ToggleButtonClick`
- `useSelect.stateChangeTypes.MenuMouseLeave`
- `useSelect.stateChangeTypes.ItemMouseMove`
- `useSelect.stateChangeTypes.ItemClick`
- `useSelect.stateChangeTypes.FunctionToggleMenu`
- `useSelect.stateChangeTypes.FunctionOpenMenu`
- `useSelect.stateChangeTypes.FunctionCloseMenu`
- `useSelect.stateChangeTypes.FunctionSetHighlightedIndex`
- `useSelect.stateChangeTypes.FunctionSelectItem`
- `useSelect.stateChangeTypes.FunctionSetInputValue`
- `useSelect.stateChangeTypes.FunctionReset`

See [`stateReducer`](#statereducer) for a concrete example on how to use the
`type` property.

## Control Props

Downshift manages its own state internally and calls your
`onSelectedItemChange`, `onIsOpenChange`, `onHighlightedIndexChange`,
`onInputChange` and `onStateChange` handlers with any relevant changes. The
state that downshift manages includes: `isOpen`, `selectedItem`, `inputValue`
and `highlightedIndex`. Returned action function (read more below) can be used
to manipulate this state and can likely support many of your use cases.

However, if more control is needed, you can pass any of these pieces of state as
a prop (as indicated above) and that state becomes controlled. As soon as
`this.props[statePropKey] !== undefined`, internally, `downshift` will determine
its state based on your prop's value rather than its own internal state. You
will be required to keep the state up to date (this is where `onStateChange`
comes in really handy), but you can also control the state from anywhere, be
that state from other components, `redux`, `react-router`, or anywhere else.

> Note: This is very similar to how normal controlled components work elsewhere
> in react (like `<input />`). If you want to learn more about this concept, you
> can learn about that from the [Advanced React Component Patterns
> course][advanced-react-component-patterns-course]

## Returned props

You use the hook like so:

```javascript
import {useSelect} from 'downshift'
import {items} from './utils'

const {getToggleButtonProps, reset, ...rest} = useSelect({
  items,
  ...otherProps,
})

return (
  <div>
    <div {...getToggleButtonProps()}>Options</div>
    {/* render the menu and items */}
    {/* render a button that resets the select to defaults */}
    <button
      onClick={() => {
        reset()
      }}
    >
      Reset
    </button>
  </div>
)
```

> NOTE: In this example we used both a getter prop `getToggleButtonProps` and an
> action prop `reset`. The properties of `useSelect` can be split into three
> categories as indicated below:

### prop getters

> See [the blog post about prop getters][blog-post-prop-getters]

> NOTE: These prop-getters provide `aria-` attributes which are very important
> to your component being accessible. It's recommended that you utilize these
> functions and apply the props they give you to your components.

These functions are used to apply props to the elements that you render. This
gives you maximum flexibility to render what, when, and wherever you like. You
call these on the element in question, for example on the toggle button:
`<button {...getToggleButtonProps()}`. It's advisable to pass all your props to
that function rather than applying them on the element yourself to avoid your
props being overridden (or overriding the props returned). For example:
`getToggleButtonProps({onKeyDown(event) {console.log(event)}})`.



| property               | type           | description                                                                                                                                     |
| ---------------------- | -------------- | ----------------------------------------------------------------------------------------------------------------------------------------------- |
| `getToggleButtonProps` | `function({})` | returns the props you should apply to the trigger element you render. Since it will receive the role of `combobox`, we chose a `<div>` element. |
| `getItemProps`         | `function({})` | returns the props you should apply to any menu item elements you render.                                                                        |
| `getLabelProps`        | `function({})` | returns the props you should apply to the `label` element that you render.                                                                      |
| `getMenuProps`         | `function({})` | returns the props you should apply to the `ul` element (or root of your menu) that you render.                                                  |

#### `getLabelProps`

This method should be applied to the `label` you render. It will generate an
`id` that will be used to label the toggle button and the menu.

There are no required properties for this method.

> Note: For accessibility purposes, calling this method is highly recommended.

#### `getMenuProps`

This method should be applied to the element which contains your list of items.
Typically, this will be a `<div>` or a `<ul>` that surrounds a `map` expression.
This handles the proper ARIA roles and attributes.

Optional properties:

- `ref`: if you need to access the menu element via a ref object, you'd call the
  function like this: `getMenuProps({ref: yourMenuRef})`. As a result, the menu
  element will receive a composed `ref` property, which guarantees that both
  your code and `useSelect` use the same correct reference to the element.

- `refKey`: if you're rendering a composite component, that component will need
  to accept a prop which it forwards to the root DOM element. Commonly, folks
  call this `innerRef`. So you'd call: `getMenuProps({refKey: 'innerRef'})` and
  your composite component would forward like: `<ul ref={props.innerRef} />`.
  However, if you are just rendering a primitive component like `<div>`, there
  is no need to specify this property. It defaults to `ref`.

  Please keep in mind that menus, for accessiblity purposes, should always be
  rendered, regardless of whether you hide it or not. Otherwise, `getMenuProps`
  may throw error if you unmount and remount the menu.

- `aria-label`: By default the menu will add an `aria-labelledby` that refers to
  the `<label>` rendered with `getLabelProps`. However, if you provide
  `aria-label` to give a more specific label that describes the options
  available, then `aria-labelledby` will not be provided and screen readers can
  use your `aria-label` instead.

In some cases, you might want to completely bypass the `refKey` check. Then you
can provide the object `{suppressRefError : true}` as the second argument to
`getMenuProps`. **Please use it with extreme care and only if you are absolutely
sure that the ref is correctly forwarded otherwise `useSelect` will unexpectedly
fail.**

```jsx
const {getMenuProps} = useSelect({items})
const ui = (
  <ul {...getMenuProps()}>
    {!isOpen
      ? null
      : items.map((item, index) => (
          <li {...getItemProps({item, index, key: item.id})}>{item.name}</li>
        ))}
  </ul>
)
```

> Note that for accessibility reasons it's best if you always render this
> element whether or not downshift is in an `isOpen` state.

#### `getItemProps`

The props returned from calling this function should be applied to any menu
items you render.

**This is an impure function**, so it should only be called when you will
actually be applying the props to an item.

<details>

<summary>What do you mean by impure function?</summary>

Basically just don't do this:

```jsx
items.map((item, index) => {
  const props = getItemProps({item, index}) // we're calling it here
  if (!shouldRenderItem(item)) {
    return null // but we're not using props, and downshift thinks we are...
  }
  return <div {...props} />
})
```

Instead, you could do this:

```jsx
items.filter(shouldRenderItem).map(item => <div {...getItemProps({item})} />)
```

</details>

Required properties:

The main difference from vanilla `Downshift` is that we require the items as
props before rendering. The reason is to open the menu with items already
highlighted, and we need to know the items before the actual render. It is still
required to pass either `item` or `index` to `getItemProps`.

- `item`: this is the item data that will be selected when the user selects a
  particular item.
- `index`: This is how `downshift` keeps track of your item when updating the
  `highlightedIndex` as the user keys around. By default, `downshift` will
  assume the `index` is the order in which you're calling `getItemProps`. This
  is often good enough, but if you find odd behavior, try setting this
  explicitly. It's probably best to be explicit about `index` when using a
  windowing library like `react-virtualized`.

Optional properties:

- `ref`: if you need to access the item element via a ref object, you'd call the
  function like this: `getItemProps({ref: yourItemRef})`. As a result, the item
  element will receive a composed `ref` property, which guarantees that both
  your code and `useSelect` use the same correct reference to the element.

- `refKey`: if you're rendering a composite component, that component will need
  to accept a prop which it forwards to the root DOM element. Commonly, folks
  call this `innerRef`. So you'd call: `getItemProps({refKey: 'innerRef'})` and
  your composite component would forward like: `<li ref={props.innerRef} />`.
  However, if you are just rendering a primitive component like `<div>`, there
  is no need to specify this property. It defaults to `ref`.

#### `getToggleButtonProps`

Call this and apply the returned props to a `div` element that will act as a
triggering button. Since ARIA 1.2, the trigger element will reiceve a `combobox`
role, so a `<button>` is not considered correct markup anymore. It allows you to
toggle the `Menu` component.

Optional properties:

- `disabled`: If this is set to `true`, then all of the downshift button event
  handlers will be omitted (it won't toggle the menu when clicked).

- `ref`: if you need to access the button element via a ref object, you'd call
  the function like this: `getToggleButtonProps({ref: yourToggleButtonRef})`. As
  a result, the button element will receive a composed `ref` property, which
  guarantees that both your code and `useSelect` use the same correct reference
  to the element.

- `refKey`: if you're rendering a composite component, that component will need
  to accept a prop which it forwards to the root DOM element. Commonly, folks
  call this `innerRef`. So you'd call: `getToggleButton({refKey: 'innerRef'})`
  and your composite component would forward like:
  `<button ref={props.innerRef} />`. However, if you are just rendering a
  primitive component like `<div>`, there is no need to specify this property.
  It defaults to `ref`.

- `aria-label`: By default the toggle element will add an `aria-labelledby` that
  refers to the `<label>` rendered with `getLabelProps`. However, if you provide
  `aria-label` to give a more specific label that describes the options
  available, then `aria-labelledby` will not be provided and screen readers can
  use your `aria-label` instead.

In some cases, you might want to completely bypass the `refKey` check. Then you
can provide the object `{suppressRefError : true}` as the second argument to
`getToggleButtonProps`. **Please use it with extreme care and only if you are
absolutely sure that the ref is correctly forwarded otherwise `useSelect` will
unexpectedly fail.**

```jsx
const {getToggleButtonProps} = useSelect({items})
const myButton = (
  <button {...getToggleButtonProps()}>Click me</button>
  {/* menu and items */}
)
```

### actions

These are functions you can call to change the state of the downshift
`useSelect` hook.



| property              | type                      | description                                           |
| --------------------- | ------------------------- | ----------------------------------------------------- |
| `closeMenu`           | `function()`              | closes the menu                                       |
| `openMenu`            | `function()`              | opens the menu                                        |
| `selectItem`          | `function(item: any)`     | selects the given item                                |
| `setHighlightedIndex` | `function(index: number)` | call to set a new highlighted index                   |
| `toggleMenu`          | `function()`              | toggle the menu open state                            |
| `reset`               | `function()`              | this resets downshift's state to a reasonable default |

### state

These are values that represent the current state of the downshift component.



| property           | type      | description                       |
| ------------------ | --------- | --------------------------------- |
| `highlightedIndex` | `number`  | the currently highlighted item    |
| `isOpen`           | `boolean` | the menu open state               |
| `selectedItem`     | `any`     | the currently selected item input |
| `keysSoFar`        | `string`  | the character keys typed so far   |

## Event Handlers

Downshift has a few events for which it provides implicit handlers. Several of
these handlers call `event.preventDefault()`. Their additional functionality is
described below.

### Default handlers

#### Toggle Button

- `Click`: If the menu is not displayed, it will open it. Otherwise it will
  close it. If there is already an item selected, the menu will be opened with
  that item already highlighted.
- `Enter`: If the menu is closed, opens the menu. If the menu is opened and
  there is an item highlighted, it will select that item.
- `Space`: If the menu is closed, opens the menu. If the menu is opened and
  there is an item highlighted, it will select that item. If the user has typed
  character keys before pressing `Space`, the space character will concatenate
  to the search query. This allows search for options such as `Republic of ..`.
- `CharacterKey`: Opens the menu if closed and highlights the first option that
  starts with that key. For instance, typing `C` will select the option that
  starts with `C`. Pressing `C` again will move the highlight to the next item
  that starts with `C`. Typing keys into rapid succession (in less than 500ms
  each) will select the option starting with that key combination, for instance
  typing `CAL` will select `californium` if this option exists.
- `ArrowDown`: If the menu is closed, it will open it. If there is already an
  item selected, it will open the menu with the selected item highlighted.
  Otherwise, it will open the menu with the first option highlighted. If the
  menu is already open, it will highlight the next item.
- `ArrowUp`: If the menu is closed, it will open it. If there is already an item
  selected, it will open the menu with the selected item highlighted. Otherwise,
  it will open the menu with the last option highlighted. If the menu is already
  open, it will highlight the previous item.
- `Alt+ArrowDown`: If the menu is closed, it will open it, without highlighting
  any item.
- `Alt+ArrowUp`: If the menu is open, it will close it and will select the item
  that was highlighted.
- `End`: If the menu is closed, it will open it. It will also highlight the last
  item in the list.
- `Home`: If the menu is closed, it will open it. It will also highlight the
  first item in the list.
- `PageUp`: If the menu is open, it will move the highlight the item 10
  positions before the current selection.
- `PageDown`: If the menu is open, it will move the highlight the item 10
  positions after the current selection.
- `Escape`: It will close the menu without selecting anything and keeps focus to
  the toggle button.
- `Blur(Tab, Shift+Tab, MouseClick outside)`: It will close the menu will select
  the highlighted item if any. Focus is handled naturally (next / previous
  elemenent in the tab order, body element if click outside.).

#### Menu

- `MouseLeave`: Will clear the value of the `highlightedIndex` if it was set.

#### Item

- `Click`: It will select the item and close the menu.
- `MouseOver`: It will highlight the item.

#### Label

- `Click`: It will move focus to the toggle element.

### Customizing Handlers

You can provide your own event handlers to `useSelect` which will be called
before the default handlers:

```javascript
const items = [...] // items here.
const {getMenuProps} = useSelect({items})
const ui = (
  /* button, label, ... */
  <ul
    {...getMenuProps({
      onKeyDown: event => {
        // your custom keyDown handler here.
      },
    })}
  />
)
```

If you would like to prevent the default handler behavior in some cases, you can
set the event's `preventDownshiftDefault` property to `true`:

```javascript
const {getMenuProps} = useSelect({items})
const ui = (
  /* button, label, ... */
  <ul
    {...getMenuProps({
      onKeyDown: event => {
        // your custom keyDown handler here.
        if (event.key === 'Enter') {
          // Prevent Downshift's default 'Enter' behavior.
          event.nativeEvent.preventDownshiftDefault = true

          // your handler code
        }
      },
    })}
  />
)
```

If you would like to completely override Downshift's behavior for a handler, in
favor of your own, you can bypass prop getters:

```javascript
const items = [...] // items here.
const {getMenuProps} = useSelect({items})
const ui = (
  /* button, label, ... */
  <ul
    {...getMenuProps()}
    onKeyDown={event => {
      // your custom keyDown handler here.
    }}
  />
)
```

## Examples

Usage examples are kept on the [downshift docsite][docsite] and also on [the
sandbox repo][sandbox-repo]. Each example has a link to its own Codesandbox
version, so check the docs.

It can be a great contributing opportunity to provide relevant use cases as
docsite examples. If you have such an example, please create an issue with the
suggestion and the Codesandbox for it, and we will take it from there.

[select-aria]:
  https://w3c.github.io/aria-practices/examples/combobox/combobox-select-only.html
[sandbox-example]:
  https://codesandbox.io/p/sandbox/github/kentcdodds/downshift-examples?file=%2Fsrc%2Fhooks%2FuseSelect%2Fbasic-usage.js&moduleview=1
[state-change-file]:
  https://github.com/downshift-js/downshift/blob/master/src/hooks/useSelect/stateChangeTypes.js
[blog-post-prop-getters]:
  https://blog.kentcdodds.com/how-to-give-rendering-control-to-users-with-prop-getters-549eaef76acf
[docsite]: https://downshift-js.com/
[sandbox-repo]:
  https://codesandbox.io/p/sandbox/github/kentcdodds/downshift-examples?file=%2Fsrc%2Findex.js&moduleview=1
[advanced-react-component-patterns-course]:
  https://github.com/downshift-js/downshift#advanced-react-component-patterns-course
[migration-guide-v7]:
  https://github.com/downshift-js/downshift/tree/master/src/hooks/MIGRATION_V7.md#useselect
[migration-guide-v8]:
  https://github.com/downshift-js/downshift/tree/master/src/hooks/MIGRATION_V8.md
[migration-guide-v9]:
  https://github.com/downshift-js/downshift/tree/master/src/hooks/MIGRATION_V9.md

---

### Overview (`src/hooks/useTagGroup/README.md`)

# useTagGroup

## The problem

You want to build a tag group component in your app that's accessible and offers
a great user experience. There is no dedicated ARIA design pattern for this
component, but since it's widely used, we compiled the list of specifications
and implemented them through a React hook that's compliant with Downshift's
principles.

## This solution

`useTagGroup` is a React hook that manages all the stateful logic needed to make
the tag group functional and accessible. It returns a set of props that are
meant to be called and their results destructured on the tag group's elements:
its container, tag item and tag remove button. The props are similar to the ones
provided by vanilla `<Downshift>` to the children render prop.

These props are called getter props, and their return values are destructured as
a set of ARIA attributes and event listeners. Together with the action props and
state props, they create all the stateful logic needed for the tag group to
implement the list of requirements. Every functionality needed should be
provided out-of-the-box: item removal and selection, and left/right arrow
movement between items, screen reader support etc.

## Table of Contents




- [Usage](#usage)
- [Basic Props](#basic-props)
  - [removeElementDescription](#removeelementdescription)
  - [onItemsChange](#onitemschange)
  - [stateReducer](#statereducer)
- [Advanced Props](#advanced-props)
  - [isItemDisabled](#isitemdisabled)
  - [initialItems](#initialitems)
  - [initialActiveIndex](#initialactiveindex)
  - [onActiveIndexChange](#onactiveindexchange)
  - [onStateChange](#onstatechange)
  - [activeIndex](#activeindex)
  - [items](#items)
  - [id](#id)
  - [tagGroupId](#taggroupid)
  - [getTagId](#gettagid)
  - [environment](#environment)
- [stateChangeTypes](#statechangetypes)
- [Control Props](#control-props)
- [Returned props](#returned-props)
  - [prop getters](#prop-getters)
    - [`getTagGroupProps`](#gettaggroupprops)
    - [`getTagProps`](#gettagprops)
    - [`getTagRemoveProps`](#gettagremoveprops)
  - [actions](#actions)
  - [state](#state)
- [Event Handlers](#event-handlers)
  - [Default handlers](#default-handlers)
    - [Tag Group](#tag-group)
    - [Tag](#tag)
  - [Tag Remove](#tag-remove)
  - [Customizing Handlers](#customizing-handlers)
- [Examples](#examples)



## Usage

> [Try it out in the browser][sandbox-example]

```
/* Detailed source-code truncated for AI context efficiency. */
```

## Basic Props

This is the list of props that you should probably know about. There are some
[advanced props](#advanced-props) below as well.

### removeElementDescription

> `string` | defaults to: `"Press Delete or Backspace to remove tag."`

An accessible description that gets added to the DOM in an invisible element and
gets picked up by screen readers when encountering tags. It should instruct
users how to remove tags with the keyboard. Useful for localized messages.

### onItemsChange

> `function(changes: object)` | optional, no useful default

Called each time the items in state changed. Adding items can be done using
`addItem`, while removing items could be done with mouse and keyboard actions.

- `changes`: These are the properties that actually have changed since the last
  state change. This object is guaranteed to contain the `items` property with
  the newly selected value. This also has a `type` property which you can learn
  more about in the [`stateChangeTypes`](#statechangetypes) section. This
  property will be part of the actions that can trigger a `items` change, for
  example `useTagGroup.stateChangeTypes.FunctionAddItem`.

### stateReducer

> `function(state: object, actionAndChanges: object)` | optional

**🚨 This is a really handy power feature 🚨**

This function will be called each time `useTagGroup` sets its internal state (or
calls your `onStateChange` handler for control props). It allows you to modify
the state change that will take place which can give you fine grain control over
how the component interacts with user updates. It gives you the current state
and the state that will be set, and you return the state that you want to set.

- `state`: The full current state of useTagGroup.
- `actionAndChanges`: Object that contains the action `type`, props needed to
  return a new state based on that type and the changes suggested by the
  useTagGroup default reducer. About the `type` property you can learn more
  about in the [`stateChangeTypes`](#statechangetypes) section.

```javascript
import {useTagGroup} from 'downshift'
import {items} from './utils'

const {getTagGroupProps, getTagProps, getTagRemoveProps, ...rest} = useTagGroup(
  {
    initialItems: items.slice(0, 4),
    stateReducer,
  },
)

function stateReducer(state, actionAndChanges) {
  const {type, changes} = actionAndChanges
  // resets active item to the first when removing an item
  switch (type) {
    case useSelect.stateChangeTypes.TagGroupKeyDownBackspace:
    case useSelect.stateChangeTypes.TagGroupKeyDownDelete:
      return {
        ...changes, // default tagGroup new state changes on item removal.
        activeIndex: changes.items.length === 0 ? -1 : 0,
      }
    default:
      return changes // otherwise business as usual.
  }
}
```

> NOTE: This is only called when state actually changes. You should not attempt
> use this to handle events. If you wish to handle events, put your event
> handlers directly on the elements (make sure to use the prop getters though!
> For example `<button onBlur={handleBlur} />` should be
> `<button {...getTagRemoveProps({onBlur: handleBlur})} />`). Also, your reducer
> function should be "pure." This means it should do nothing other than return
> the state changes you want to have happen.

## Advanced Props

### isItemDisabled

> `function(item: any, index: number)` | defaults to: `(_item, _index) => false`

If an item needs to be marked as disabled, this function needs to return `true`
for that item. Disabled items will be skipped from keyboard navigation, will not
be removed and will be marked as disabled for screen readers.

### initialItems

> `any[]` | defaults to `null`

Pass an items collection that should be selected when useTagGroup is
initialized.

### initialActiveIndex

> `number` | defaults to `0` if there are initial items or `-1` otherwise.

Pass a boolean that sets the open state of the menu when useTagGroup is
initialized.

### onActiveIndexChange

> `function(changes: object)` | optional, no useful default

Called each time the active index was changed. Active item can be changed by
clicking the tag or by using left and right arrows while a tag is focused.

- `changes`: These are the properties that actually have changed since the last
  state change. This object is guaranteed to contain the `activeIndex` property
  with the new value. This also has a `type` property which you can learn more
  about in the [`stateChangeTypes`](#statechangetypes) section. This property
  will be part of the actions that can trigger a `activeIndex` change, for
  example `useTagGroup.stateChangeTypes.TagGroupKeyDownArrowRight`.

### onStateChange

> `function(changes: object)` | optional, no useful default

This function is called anytime the internal state changes. This can be useful
if you're using useTagGroup as a "controlled" hook, where you manage some or all
of the state (e.g., isOpen, selectedItem, highlightedIndex, etc) and then pass
it as props, rather than letting useTagGroup control all its state itself.

- `changes`: These are the properties that actually have changed since the last
  state change. This also has a `type` property which you can learn more about
  in the [`stateChangeTypes`](#statechangetypes) section.

> Tip: This function will be called any time _any_ state is changed. The best
> way to determine whether any particular state was changed, you can use
> `changes.hasOwnProperty('propName')` or use the `on[statePropKey]Change` props
> described above.

> NOTE: This is only called when state actually changes. You should not attempt
> to use this to handle events. If you wish handle events, put your event
> handlers directly on the elements (make sure to use the prop getters though!
> For example: `<span onBlur={handleBlur} />` should be
> `<span {...getTagProps({onBlur: handleBlur})} />`).

### activeIndex

> `number` | **control prop** (read more about this in
> [the Control Props section](#control-props))

The index of the item that should be active so that it receives focus.

### items

> `any[]` | **control prop** (read more about this in
> [the Control Props section](#control-props))

The items that are part of the tag group

### id

> `string` | defaults to a generated ID

Used to generate the first part of the useTagGroup id on the elements. You can
override this `id` with one of your own, provided as a prop, or you can override
the `id` for each element altogether using the props below.

### tagGroupId

> `string` | defaults to a generated ID

Used for `aria` attributes and the `id` prop of the element you use
[`getTagGroupProps`](#gettaggroupprops) with.

### getTagId

> `function(index)` | defaults to a function that generates an ID based on the
> index

Used for `aria` attributes and the `id` prop of the element (`li`) you use
[`getTagProps`](#gettagprops) and [`getTagRemoveProps`](#gettagremoveprops)
with.

### environment

> `window` | defaults to `window`

This prop is only useful if you're rendering downshift within a different
`window` context from where your JavaScript is running; for example, an iframe
or a shadow-root. If the given context is lacking `document` and/or
`add|removeEventListener` on its prototype (as is the case for a shadow-root)
then you will need to pass in a custom object that is able to provide
[access to these properties](https://gist.github.com/Rendez/1dd55882e9b850dd3990feefc9d6e177)
for downshift.

## stateChangeTypes

There are a few props that expose changes to state
([`onStateChange`](#onstatechange) and [`stateReducer`](#statereducer)). For you
to make the most of these APIs, it's important for you to understand why state
is being changed. To accomplish this, there's a `type` property on the `changes`
object you get. This `type` corresponds to a `stateChangeTypes` property.

The list of all possible values this `type` property can take is defined in
[this file][state-change-file] and is as follows:

- `useTagGroup.stateChangeTypes.TagClick`
- `useTagGroup.stateChangeTypes.TagGroupKeyDownArrowLeft`
- `useTagGroup.stateChangeTypes.TagGroupKeyDownArrowRight`
- `useTagGroup.stateChangeTypes.TagGroupKeyDownBackspace`
- `useTagGroup.stateChangeTypes.TagGroupKeyDownDelete`
- `useTagGroup.stateChangeTypes.TagRemoveClick`
- `useTagGroup.stateChangeTypes.FunctionAddItem`

See [`stateReducer`](#statereducer) for a concrete example on how to use the
`type` property.

## Control Props

Downshift manages its own state internally and calls your `onItemsChange`,
`onActiveIndexChange` and `onStateChange` handlers with any relevant changes.
The state that downshift manages includes: `items` and `activeIndex`. Returned
action function (read more below) can be used to manipulate this state and can
likely support many of your use cases.

However, if more control is needed, you can pass any of these pieces of state as
a prop (as indicated above) and that state becomes controlled. As soon as
`this.props[statePropKey] !== undefined`, internally, `downshift` will determine
its state based on your prop's value rather than its own internal state. You
will be required to keep the state up to date (this is where `onStateChange`
comes in really handy), but you can also control the state from anywhere, be
that state from other components, `redux`, `react-router`, or anywhere else.

> Note: This is very similar to how normal controlled components work elsewhere
> in react (like `<input />`). If you want to learn more about this concept, you
> can learn about that from the [Advanced React Component Patterns
> course][advanced-react-component-patterns-course]

## Returned props

You use the hook like so:

```javascript
import {useTagGroup} from 'downshift'
import {items} from './utils'

const {getTagGroupProps, addItem, ...rest} = useTagGroup({
  initialItems: items.slice(0, 2),
  ...otherProps,
})

return (
  <div>
    <div {...getTagGroupProps()}>{/* render the items */}</div>
    <div>
      {/* render items to be added */}
      <button
        onClick={() => {
          addItem(itemToBeAdded)
        }}
      >
        {`Add ${itemToBeAdded.title}`}
      </button>
    </div>
  </div>
)
```

> NOTE: In this example we used both a getter prop `getTagGroupProps` and an
> action prop `addItem`. The properties of `useTagGroup` can be split into three
> categories as indicated below:

### prop getters

> See [the blog post about prop getters][blog-post-prop-getters]

> NOTE: These prop-getters provide `aria-` attributes which are very important
> to your component being accessible. It's recommended that you utilize these
> functions and apply the props they give you to your components.

These functions are used to apply props to the elements that you render. This
gives you maximum flexibility to render what, when, and wherever you like. You
call these on the element in question, for example on the toggle button:
`<button {...getTagRemoveProps()}`. It's advisable to pass all your props to
that function rather than applying them on the element yourself to avoid your
props being overridden (or overriding the props returned). For example:
`getTagRemoveProps({onKeyDown(event) {console.log(event)}})`.



| property            | type           | description                                                                          |
| ------------------- | -------------- | ------------------------------------------------------------------------------------ |
| `getTagGroupProps`  | `function({})` | returns the props you should apply to the tag group container element you render.    |
| `getTagProps`       | `function({})` | returns the props you should apply to any tag elements you render.                   |
| `getTagRemoveProps` | `function({})` | returns the props you should apply to the tag remove button element that you render. |
|                     |

#### `getTagGroupProps`

This method should be applied to the tag group container you render. It applies
a `listbox` role along with some other ARIA properties and event handlers.

#### `getTagProps`

This method should be applied to the tag element that makes up the list of tags
in the tag group. Typically, this will be a `<span>` or a `<div>`. This applies
ARIA attributes and event handlers.

Required properties:

- `index`: This is how `useTagRemoveGroup` keeps track of your item when
  changing the active element through `activeIndex`. By default,
  `useTagRemoveGroup` will assume the `index` is the order in which you're
  calling `getTagProps`. This is often good enough, but if you find odd
  behavior, try setting this explicitly. It's probably best to be explicit about
  `index` when using a windowing library like `react-virtualized`.

Optional properties:

- `ref`: if you need to access the menu element via a ref object, you'd call the
  function like this: `getTagProps({ref: yourTagRef})`. As a result, the tag
  element will receive a composed `ref` property, which guarantees that both
  your code and `useTagGroup` use the same correct reference to the element.

- `refKey`: if you're rendering a composite component, that component will need
  to accept a prop which it forwards to the root DOM element. Commonly, folks
  call this `innerRef`. So you'd call: `getTagProps({refKey: 'innerRef'})` and
  your composite component would forward like: `<span ref={props.innerRef} />`.
  However, if you are just rendering a primitive component like `<div>`, there
  is no need to specify this property. It defaults to `ref`.

In some cases, you might want to completely bypass the `refKey` check. Then you
can provide the object `{suppressRefError : true}` as the second argument to
`getTagProps`. **Please use it with extreme care and only if you are absolutely
sure that the ref is correctly forwarded otherwise `useTagGroup` will
unexpectedly fail.**

```jsx
const {getTagProps, getTagGroupProps, items} = useTagGroup()
const ui = (
  <div {...getTagGroupProps()}>
    {!items.length === 0
      ? null
      : items.map((item, index) => (
          <span {...getTagProps({index, key: item.id})}>{item.name}</span>
        ))}
  </div>
)
```

**This is an impure function**, so it should only be called when you will
actually be applying the props to an item.

<details>

<summary>What do you mean by impure function?</summary>

Basically just don't do this:

```jsx
items.map((item, index) => {
  const props = getTagProps({item, index}) // we're calling it here
  if (!shouldRenderItem(item)) {
    return null // but we're not using props, and downshift thinks we are...
  }
  return <div {...props} />
})
```

Instead, you could do this:

```jsx
items.filter(shouldRenderItem).map(item => <div {...getTagProps({item})} />)
```

</details>

#### `getTagRemoveProps`

The props returned from calling this function should be applied to the remove
button element for each tag, if there is need for such an element

**This is an impure function**, same as `getTagProps`.

```jsx
// rendering the tag
<span {...getTagProps({index, key: item.id})}>
  {item.name}
  <button {...getTagRemoveProps({index, 'aria-label': 'Remove'})}>X</button>
</span>
```

Required properties:

- `index`: This is how `useTagRemoveGroup` keeps track of your item when
  labelling the remove button. By default, `useTagRemoveGroup` will assume the
  `index` is the order in which you're calling `getItemProps`. This is often
  good enough, but if you find odd behavior, try setting this explicitly. It's
  probably best to be explicit about `index` when using a windowing library like
  `react-virtualized`.

Optional properties:

- `ref`: if you need to access the item element via a ref object, you'd call the
  function like this: `getTagRemoveProps({ref: yourTagRef})`. As a result, the
  tag element will receive a composed `ref` property, which guarantees that both
  your code and `useSelect` use the same correct reference to the element.

- `refKey`: if you're rendering a composite component, that component will need
  to accept a prop which it forwards to the root DOM element. Commonly, folks
  call this `innerRef`. So you'd call: `getTagRemoveProps({refKey: 'innerRef'})`
  and your composite component would forward like:
  `<button ref={props.innerRef} />`. However, if you are just rendering a
  primitive component like `<div>`, there is no need to specify this property.
  It defaults to `ref`.

### actions

These are functions you can call to change the state of the downshift
`useTagGroup` hook.



| property  | type                  | description                              |
| --------- | --------------------- | ---------------------------------------- |
| `addItem` | `function(item: any)` | it adds the given item to the collection |

### state

These are values that represent the current state of the downshift component.



| property      | type     | description                |
| ------------- | -------- | -------------------------- |
| `activeIndex` | `number` | the currently active item  |
| `items`       | `any[]`  | the items in the selection |

## Event Handlers

Downshift has a few events for which it provides implicit handlers. Several of
these handlers call `event.preventDefault()`. Their additional functionality is
described below.

### Default handlers

#### Tag Group

- `ArrowLeft`: if a tag is focused and there are multiple tags in the tag group,
  it will move focus to the tag that's placed to the left. If the tag has no
  neighbours to the left, it will move focus to the last tag.
- `ArrowRight`: if a tag is focused and there are multiple tags in the tag
  group, it will move focus to the tag that's placed to the right. If the tag
  has no neighbours to the right, it will move focus to the first tag.

#### Tag

- `Click`: moves the focus to this tag. Useful to execute optional actions as
  well, such as opening a non-modal with additional information.
- `Delete, Backspace`: removes the tag from the tag group and moves the focus to
  either the next or previous tag, depending on the removed tag index.

### Tag Remove

- `Click`: removes the tag from the tag group and moves the focus to either the
  next or previous tag, depending on the removed tag index.

### Customizing Handlers

You can provide your own event handlers to `useTagGroup` which will be called
before the default handlers:

```javascript
const items = [...] // items here.
const {getTagGroup} = useTagGroup({initialItems: items})
const ui = (
  <div
    {...getTagGroup({
      onKeyDown: event => {
        // your custom keyDown handler here.
      },
    })}
  />
)
```

If you would like to prevent the default handler behavior in some cases, you can
set the event's `preventDownshiftDefault` property to `true`:

```javascript
const items = [...] // items here.
const {getTagGroup} = useTagGroup({initialItems: items})
const ui = (
  <div
    {...getTagGroup({
      onKeyDown: event => {
        // your custom keyDown handler here.
        if (event.key === 'ArrowLeft' || event.key === 'ArrowRight') {
          // Prevent Downshift's default 'Enter' behavior.
          event.nativeEvent.preventDownshiftDefault = true

          // your handler code
        }
      },
    })}
  />
)
```

If you would like to completely override Downshift's behavior for a handler, in
favor of your own, you can bypass prop getters:

```javascript
const items = [...] // items here.
const {getTagGroup} = useTagGroup({initialItems: items})
const ui = (
  <div
    {...getTagGroup()}
    onKeyDown={event => {
      // your custom keyDown handler here.
    }}
  />
)
```

## Examples

Usage examples are kept on the [downshift docsite][docsite] and also on [the
sandbox repo][sandbox-repo]. Each example has a link to its own Codesandbox
version, so check the docs.

It can be a great contributing opportunity to provide relevant use cases as
docsite examples. If you have such an example, please create an issue with the
suggestion and the Codesandbox for it, and we will take it from there.

[sandbox-example]:
  https://codesandbox.io/p/sandbox/github/kentcdodds/downshift-examples?file=%2Fsrc%2Fhooks%2FuseTagGroup%2Fbasic-usage.js&moduleview=1
[state-change-file]:
  https://github.com/downshift-js/downshift/blob/master/src/hooks/useTagGroup/stateChangeTypes.ts
[blog-post-prop-getters]:
  https://blog.kentcdodds.com/how-to-give-rendering-control-to-users-with-prop-getters-549eaef76acf
[docsite]: https://downshift-js.com/
[sandbox-repo]:
  https://codesandbox.io/p/sandbox/github/kentcdodds/downshift-examples?file=%2Fsrc%2Findex.js&moduleview=1
[advanced-react-component-patterns-course]:
  https://github.com/downshift-js/downshift#advanced-react-component-patterns-course

---

--- METRICS ---
- Files Extracted: 6
- Estimated Token Budget: ~62484 tokens
- Canonical Reference: https://codewiki.google/github.com/downshift-js/downshift
