# Filterable list with React

How to make a list with a search field so the user can filter the list.

## Demo

This is what we’re building:

[Interactive example](/filterable-list)

## The React component

Here’s code for that example:

```tsx showLineNumbers
import type { ChangeEvent, ComponentProps } from 'react'
import { useState } from 'react'

const items = ['foo', 'fooz', 'bar', 'baz', 'quix']

export function FilterableList({ style, ...props }: ComponentProps<'div'>) {
  const [searchResults, setSearchResults] = useState(items)

  const handleChange = (event: ChangeEvent<HTMLInputElement>) => {
    const value = event.target.value.toLowerCase()

    if (value) {
      const results = items.filter(item => item.toLowerCase().includes(value))
      setSearchResults(results.length > 0 || value ? results : items)
    } else {
      setSearchResults(items)
    }
  }

  return (
    <div
      {...props}
      style={{
        border: '1px solid #ddd',
        padding: '20px 20px 10px 20px',
        ...style,
      }}
    >
      <input
        aria-controls='tag-list'
        onChange={handleChange}
        placeholder='Search'
        style={{ padding: '5px 10px', marginBottom: '10px', ...style }}
        type='text'
      />
      <ul aria-live='polite' id='tag-list' role='region'>
        {searchResults.length === 0 ? (
          <li>No results</li>
        ) : (
          searchResults.map(item => <li key={item}>{item}</li>)
        )}
      </ul>
    </div>
  )
}
```

## Accessibility

We need to tell screen readers to announce the changes that have happened on the
page when filtering. This can be done by defining the list as an
[ARIA live region](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/ARIA_Live_Regions),
see the highlighted lines and the explanation below:

ARIA stands for: Accessible Rich Internet Applications

```jsx showLineNumbers
<>
  <input
    aria-controls='tag-list'
    aria-label='search'
    onChange={handleChange}
    placeholder='Search'
    style={{ padding: '5px 10px', marginBottom: '10px', ...style }}
    type='text'
  />
  <ul aria-live='polite' id='tag-list' role='region'>
    {searchResults.length === 0 ? (
      <li>No results</li>
    ) : (
      searchResults.map(item => <li key={item}>{item}</li>)
    )}
  </ul>
</>
```

aria-controls="tag-list"

This attribute tells the screen reader that this field controls the list
    below with the id of `tag-list`.

aria-label="search"

We don’t have a label on the form field, so we can label it like this.

aria-live="polite"

This marks the element as a live region, meaning it might update
    dynamically. The value of the attribute defines how the changes to the
    `tag-list` are announced. Other values can be `assertive` or
    `off`.

role="region"

The region role is used to identify document areas the author deems
      significant. It is a generic landmark available to aid in navigation when
      none of the other landmark roles are appropriate.



[Read more about regions](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Roles/region_role)

.
